diff options
| author | lrh2000 <lrh2000@pku.edu.cn> | 2021-05-15 19:01:13 +0800 |
|---|---|---|
| committer | lrh2000 <lrh2000@pku.edu.cn> | 2021-07-09 23:09:48 +0800 |
| commit | cda90f55419ce449f3a9db327465d9b2ae7dfce9 (patch) | |
| tree | 16325f4b16e3865b249ebcc2182eaea1a2ca54b1 /compiler/rustc_codegen_llvm/src/debuginfo | |
| parent | 29856acffeb87541bb167c33f4fdb13c31ba6de0 (diff) | |
| download | rust-cda90f55419ce449f3a9db327465d9b2ae7dfce9.tar.gz rust-cda90f55419ce449f3a9db327465d9b2ae7dfce9.zip | |
Store names of captured variables in `optimized_mir`
- Closures in external crates may get compiled in because of monomorphization. We should store names of captured variables in `optimized_mir`, so that they are written into the metadata file and we can use them to generate debuginfo. - If there are breakpoints inside closures, the names of captured variables stored in `optimized_mir` can be used to print them. Now the name is more precise when disjoint fields are captured.
Diffstat (limited to 'compiler/rustc_codegen_llvm/src/debuginfo')
| -rw-r--r-- | compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs | 52 |
1 files changed, 33 insertions, 19 deletions
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index 60c6bd61cd7..bc950778bcc 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -1280,6 +1280,31 @@ fn prepare_struct_metadata( // Tuples //=----------------------------------------------------------------------------- +/// Returns names of captured upvars for closures and generators. +/// +/// Here are some examples: +/// - `name__field1__field2` when the upvar is captured by value. +/// - `_ref__name__field` when the upvar is captured by reference. +fn closure_saved_names_of_captured_variables(tcx: TyCtxt<'tcx>, def_id: DefId) -> Vec<String> { + let body = tcx.optimized_mir(def_id); + + body.var_debug_info + .iter() + .filter_map(|var| { + let is_ref = match var.value { + mir::VarDebugInfoContents::Place(place) if place.local == mir::Local::new(1) => { + // The projection is either `[.., Field, Deref]` or `[.., Field]`. It + // implies whether the variable is captured by value or by reference. + matches!(place.projection.last().unwrap(), mir::ProjectionElem::Deref) + } + _ => return None, + }; + let prefix = if is_ref { "_ref__" } else { "" }; + Some(prefix.to_owned() + &var.name.as_str()) + }) + .collect::<Vec<_>>() +} + /// Creates `MemberDescription`s for the fields of a tuple. struct TupleMemberDescriptionFactory<'tcx> { ty: Ty<'tcx>, @@ -1289,34 +1314,23 @@ struct TupleMemberDescriptionFactory<'tcx> { impl<'tcx> TupleMemberDescriptionFactory<'tcx> { fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>) -> Vec<MemberDescription<'ll>> { - // For closures and generators, name the captured upvars - // with the help of `CapturedPlace::to_mangled_name`. - 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) + let capture_names = match *self.ty.kind() { + ty::Generator(def_id, ..) | ty::Closure(def_id, ..) => { + Some(closure_saved_names_of_captured_variables(cx.tcx, def_id)) } _ => None, }; - 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); - let name = captures - .as_ref() - .map(|c| c[i].to_mangled_name(cx.tcx)) - .unwrap_or_else(|| format!("__{}", i)); + let name = if let Some(names) = capture_names.as_ref() { + names[i].clone() + } else { + format!("__{}", i) + }; MemberDescription { name, type_metadata: type_metadata(cx, component_type, self.span), |
