Skip to content

Commit

Permalink
Auto merge of #85269 - dpaoliello:dpaoliello/DebugSymbols, r=michaelw…
Browse files Browse the repository at this point in the history
…oerister

Improve debug symbol names to avoid ambiguity and work better with MSVC's debugger

There are several cases where names of types and functions in the debug info are either ambiguous, or not helpful, such as including ambiguous placeholders (e.g., `{{impl}}`, `{{closure}}` or `dyn _'`) or dropping qualifications (e.g., for dynamic types).

Instead, each debug symbol name should be unique and useful:
* Include disambiguators for anonymous `DefPathDataName` (closures and generators), and unify their formatting when used as a path-qualifier vs item being qualified.
* Qualify the principal trait for dynamic types.
* If there is no principal trait for a dynamic type, emit all other traits instead.
* Respect the `qualified` argument when emitting ref and pointer types.
* For implementations, emit the disambiguator.
* Print const generics when emitting generic parameters or arguments.

Additionally, when targeting MSVC, its debugger treats many command arguments as C++ expressions, even when the argument is defined to be a symbol name. As such names in the debug info need to be more C++-like to be parsed correctly:
* Avoid characters with special meaning (`#`, `[`, `"`, `+`).
* Never start a name with `<` or `{` as this is treated as an operator.
* `>>` is always treated as a right-shift, even when parsing generic arguments (so add a space to avoid this).
* Emit function declarations using C/C++ style syntax (e.g., leading return type).
* Emit arrays as a synthetic `array$<type, size>` type.
* Include a `$` in all synthetic types as this is a legal character for C++, but not Rust (thus we avoid collisions with user types).
  • Loading branch information
bors committed Jul 2, 2021
2 parents 851c82e + c1601dc commit 2545459
Show file tree
Hide file tree
Showing 30 changed files with 853 additions and 341 deletions.
37 changes: 22 additions & 15 deletions compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -471,21 +471,28 @@ fn trait_pointer_metadata(
// type is assigned the correct name, size, namespace, and source location.
// However, it does not describe the trait's methods.

let containing_scope = match trait_type.kind() {
ty::Dynamic(ref data, ..) => {
data.principal_def_id().map(|did| get_namespace_for_item(cx, did))
}
_ => {
bug!(
"debuginfo: unexpected trait-object type in \
trait_pointer_metadata(): {:?}",
trait_type
);
}
};
let (containing_scope, trait_type_name) = match trait_object_type {
Some(trait_object_type) => match trait_object_type.kind() {
ty::Adt(def, _) => (
Some(get_namespace_for_item(cx, def.did)),
compute_debuginfo_type_name(cx.tcx, trait_object_type, false),
),
ty::RawPtr(_) | ty::Ref(..) => {
(NO_SCOPE_METADATA, compute_debuginfo_type_name(cx.tcx, trait_object_type, true))
}
_ => {
bug!(
"debuginfo: unexpected trait-object type in \
trait_pointer_metadata(): {:?}",
trait_object_type
);
}
},

let trait_object_type = trait_object_type.unwrap_or(trait_type);
let trait_type_name = compute_debuginfo_type_name(cx.tcx, trait_object_type, false);
// No object type, use the trait type directly (no scope here since the type
// will be wrapped in the dyn$ synthetic type).
None => (NO_SCOPE_METADATA, compute_debuginfo_type_name(cx.tcx, trait_type, true)),
};

let file_metadata = unknown_file_metadata(cx);

Expand Down Expand Up @@ -525,7 +532,7 @@ fn trait_pointer_metadata(

composite_type_metadata(
cx,
trait_object_type,
trait_object_type.unwrap_or(trait_type),
&trait_type_name[..],
unique_type_id,
member_descriptions,
Expand Down
27 changes: 9 additions & 18 deletions compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ use rustc_codegen_ssa::mir::debuginfo::VariableKind::*;
use self::metadata::{file_metadata, type_metadata, TypeMap};
use self::metadata::{UNKNOWN_COLUMN_NUMBER, UNKNOWN_LINE_NUMBER};
use self::namespace::mangled_name_of_instance;
use self::type_names::compute_debuginfo_type_name;
use self::utils::{create_DIArray, is_node_local_to_unit, DIB};

use crate::abi::FnAbi;
Expand Down Expand Up @@ -311,10 +310,10 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
llvm::LLVMRustDIBuilderCreateSubroutineType(DIB(self), fn_signature)
};

// Find the enclosing function, in case this is a closure.
let def_key = self.tcx().def_key(def_id);
let mut name = def_key.disambiguated_data.data.to_string();
let mut name = String::new();
type_names::push_item_name(self.tcx(), def_id, false, &mut name);

// Find the enclosing function, in case this is a closure.
let enclosing_fn_def_id = self.tcx().closure_base_def_id(def_id);

// Get_template_parameters() will append a `<...>` clause to the function
Expand Down Expand Up @@ -428,24 +427,16 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
substs: SubstsRef<'tcx>,
name_to_append_suffix_to: &mut String,
) -> &'ll DIArray {
type_names::push_generic_params(
cx.tcx,
cx.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), substs),
name_to_append_suffix_to,
);

if substs.types().next().is_none() {
return create_DIArray(DIB(cx), &[]);
}

name_to_append_suffix_to.push('<');
for (i, actual_type) in substs.types().enumerate() {
if i != 0 {
name_to_append_suffix_to.push(',');
}

let actual_type =
cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), actual_type);
// Add actual type name to <...> clause of function name
let actual_type_name = compute_debuginfo_type_name(cx.tcx(), actual_type, true);
name_to_append_suffix_to.push_str(&actual_type_name[..]);
}
name_to_append_suffix_to.push('>');

// Again, only create type information if full debuginfo is enabled
let template_params: Vec<_> = if cx.sess().opts.debuginfo == DebugInfo::Full {
let names = get_parameter_names(cx, generics);
Expand Down
21 changes: 7 additions & 14 deletions compiler/rustc_codegen_llvm/src/debuginfo/namespace.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
// Namespace Handling.

use super::utils::{debug_context, DIB};
use rustc_codegen_ssa::debuginfo::type_names;
use rustc_middle::ty::{self, Instance};

use crate::common::CodegenCx;
use crate::llvm;
use crate::llvm::debuginfo::DIScope;
use rustc_hir::def_id::DefId;
use rustc_hir::definitions::DefPathData;

pub fn mangled_name_of_instance<'a, 'tcx>(
cx: &CodegenCx<'a, 'tcx>,
Expand All @@ -27,25 +27,18 @@ pub fn item_namespace(cx: &CodegenCx<'ll, '_>, def_id: DefId) -> &'ll DIScope {
.parent
.map(|parent| item_namespace(cx, DefId { krate: def_id.krate, index: parent }));

let crate_name_as_str;
let name_to_string;
let namespace_name = match def_key.disambiguated_data.data {
DefPathData::CrateRoot => {
crate_name_as_str = cx.tcx.crate_name(def_id.krate).as_str();
&*crate_name_as_str
}
data => {
name_to_string = data.to_string();
&*name_to_string
}
let namespace_name_string = {
let mut output = String::new();
type_names::push_item_name(cx.tcx, def_id, false, &mut output);
output
};

let scope = unsafe {
llvm::LLVMRustDIBuilderCreateNameSpace(
DIB(cx),
parent_scope,
namespace_name.as_ptr().cast(),
namespace_name.len(),
namespace_name_string.as_ptr().cast(),
namespace_name_string.len(),
false, // ExportSymbols (only relevant for C++ anonymous namespaces)
)
};
Expand Down
Loading

0 comments on commit 2545459

Please sign in to comment.