Rollup merge of #81898 - nanguye2496:nanguye2496/fix_str_and_slice_visualization, r=varkor

Fix debug information for function arguments of type &str or slice.

Issue details:
When lowering MIR to LLVM IR, the compiler decomposes every &str and slice argument into a data pointer and a usize. Then, the original argument is reconstructed from the pointer and the usize arguments in the body of the function that owns it. Since the original argument is declared in the body of a function, it should be marked as a LocalVariable instead of an ArgumentVairable. This confusion causes MSVC debuggers unable to visualize &str and slice arguments correctly. (See https://github.com/rust-lang/rust/issues/81894 for more details).

Fix details:
Making sure that the debug variable for every &str and slice argument is marked as LocalVariable instead of ArgumentVariable in computing_per_local_var_debug_info. This change has been verified on VS Code debugger, VS debugger, WinDbg and LLDB.
This commit is contained in:
Dylan DPC 2021-02-17 23:51:17 +01:00 committed by GitHub
commit f79be2c6de
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -320,6 +320,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
) -> Option<IndexVec<mir::Local, Vec<PerLocalVarDebugInfo<'tcx, Bx::DIVariable>>>> { ) -> Option<IndexVec<mir::Local, Vec<PerLocalVarDebugInfo<'tcx, Bx::DIVariable>>>> {
let full_debug_info = self.cx.sess().opts.debuginfo == DebugInfo::Full; let full_debug_info = self.cx.sess().opts.debuginfo == DebugInfo::Full;
let target_is_msvc = self.cx.sess().target.is_like_msvc;
if !full_debug_info && self.cx.sess().fewer_names() { if !full_debug_info && self.cx.sess().fewer_names() {
return None; return None;
} }
@ -341,11 +343,29 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
&& var.source_info.scope == mir::OUTERMOST_SOURCE_SCOPE && var.source_info.scope == mir::OUTERMOST_SOURCE_SCOPE
{ {
let arg_index = place.local.index() - 1; let arg_index = place.local.index() - 1;
if target_is_msvc {
// FIXME(eddyb) shouldn't `ArgumentVariable` indices be // Rust compiler decomposes every &str or slice argument into two components:
// offset in closures to account for the hidden environment? // a pointer to the memory address where the data is stored and a usize representing
// Also, is this `+ 1` needed at all? // the length of the str (or slice). These components will later be used to reconstruct
VariableKind::ArgumentVariable(arg_index + 1) // the original argument inside the body of the function that owns it (see the
// definition of debug_introduce_local for more details).
//
// Since the original argument is declared inside a function rather than being passed
// in as an argument, it must be marked as a LocalVariable for MSVC debuggers to visualize
// its data correctly. (See issue #81894 for an in-depth description of the problem).
match *var_ty.kind() {
ty::Ref(_, inner_type, _) => match *inner_type.kind() {
ty::Slice(_) | ty::Str => VariableKind::LocalVariable,
_ => VariableKind::ArgumentVariable(arg_index + 1),
},
_ => VariableKind::ArgumentVariable(arg_index + 1),
}
} else {
// FIXME(eddyb) shouldn't `ArgumentVariable` indices be
// offset in closures to account for the hidden environment?
// Also, is this `+ 1` needed at all?
VariableKind::ArgumentVariable(arg_index + 1)
}
} else { } else {
VariableKind::LocalVariable VariableKind::LocalVariable
}; };