Skip to content

Commit 0da6d42

Browse files
committed
Auto merge of #68965 - eddyb:mir-inline-scope, r=nagisa,oli-obk
rustc_mir: track inlined callees in SourceScopeData. We now record which MIR scopes are the roots of *other* (inlined) functions's scope trees, which allows us to generate the correct debuginfo in codegen, similar to what LLVM inlining generates. This PR makes the `ui` test `backtrace-debuginfo` pass, if the MIR inliner is turned on by default. Also, `#[track_caller]` is now correct in the face of MIR inlining (cc `@anp).` Fixes #76997. r? `@rust-lang/wg-mir-opt`
2 parents 35debd4 + 2b3f009 commit 0da6d42

File tree

68 files changed

+878
-618
lines changed

Some content is hidden

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

68 files changed

+878
-618
lines changed

compiler/rustc_codegen_llvm/src/builder.rs

+1
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ impl BackendTypes for Builder<'_, 'll, 'tcx> {
5656
type Funclet = <CodegenCx<'ll, 'tcx> as BackendTypes>::Funclet;
5757

5858
type DIScope = <CodegenCx<'ll, 'tcx> as BackendTypes>::DIScope;
59+
type DILocation = <CodegenCx<'ll, 'tcx> as BackendTypes>::DILocation;
5960
type DIVariable = <CodegenCx<'ll, 'tcx> as BackendTypes>::DIVariable;
6061
}
6162

compiler/rustc_codegen_llvm/src/common.rs

+2
Original file line numberDiff line numberDiff line change
@@ -80,13 +80,15 @@ impl Funclet<'ll> {
8080

8181
impl BackendTypes for CodegenCx<'ll, 'tcx> {
8282
type Value = &'ll Value;
83+
// FIXME(eddyb) replace this with a `Function` "subclass" of `Value`.
8384
type Function = &'ll Value;
8485

8586
type BasicBlock = &'ll BasicBlock;
8687
type Type = &'ll Type;
8788
type Funclet = Funclet<'ll>;
8889

8990
type DIScope = &'ll llvm::debuginfo::DIScope;
91+
type DILocation = &'ll llvm::debuginfo::DILocation;
9092
type DIVariable = &'ll llvm::debuginfo::DIVariable;
9193
}
9294

compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs

+55-26
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,26 @@ use super::utils::DIB;
33
use rustc_codegen_ssa::mir::debuginfo::{DebugScope, FunctionDebugContext};
44
use rustc_codegen_ssa::traits::*;
55

6+
use crate::abi::FnAbi;
67
use crate::common::CodegenCx;
78
use crate::llvm;
8-
use crate::llvm::debuginfo::{DIScope, DISubprogram};
9+
use crate::llvm::debuginfo::{DILocation, DIScope};
910
use rustc_middle::mir::{Body, SourceScope};
11+
use rustc_middle::ty::layout::FnAbiExt;
12+
use rustc_middle::ty::{self, Instance};
1013
use rustc_session::config::DebugInfo;
1114

1215
use rustc_index::bit_set::BitSet;
1316
use rustc_index::vec::Idx;
1417

1518
/// Produces DIScope DIEs for each MIR Scope which has variables defined in it.
19+
// FIXME(eddyb) almost all of this should be in `rustc_codegen_ssa::mir::debuginfo`.
1620
pub fn compute_mir_scopes(
17-
cx: &CodegenCx<'ll, '_>,
18-
mir: &Body<'_>,
19-
fn_metadata: &'ll DISubprogram,
20-
debug_context: &mut FunctionDebugContext<&'ll DIScope>,
21+
cx: &CodegenCx<'ll, 'tcx>,
22+
instance: Instance<'tcx>,
23+
mir: &Body<'tcx>,
24+
fn_dbg_scope: &'ll DIScope,
25+
debug_context: &mut FunctionDebugContext<&'ll DIScope, &'ll DILocation>,
2126
) {
2227
// Find all the scopes with variables defined in them.
2328
let mut has_variables = BitSet::new_empty(mir.source_scopes.len());
@@ -37,58 +42,82 @@ pub fn compute_mir_scopes(
3742
// Instantiate all scopes.
3843
for idx in 0..mir.source_scopes.len() {
3944
let scope = SourceScope::new(idx);
40-
make_mir_scope(cx, &mir, fn_metadata, &has_variables, debug_context, scope);
45+
make_mir_scope(cx, instance, &mir, fn_dbg_scope, &has_variables, debug_context, scope);
4146
}
4247
}
4348

4449
fn make_mir_scope(
45-
cx: &CodegenCx<'ll, '_>,
46-
mir: &Body<'_>,
47-
fn_metadata: &'ll DISubprogram,
50+
cx: &CodegenCx<'ll, 'tcx>,
51+
instance: Instance<'tcx>,
52+
mir: &Body<'tcx>,
53+
fn_dbg_scope: &'ll DIScope,
4854
has_variables: &BitSet<SourceScope>,
49-
debug_context: &mut FunctionDebugContext<&'ll DISubprogram>,
55+
debug_context: &mut FunctionDebugContext<&'ll DIScope, &'ll DILocation>,
5056
scope: SourceScope,
5157
) {
52-
if debug_context.scopes[scope].is_valid() {
58+
if debug_context.scopes[scope].dbg_scope.is_some() {
5359
return;
5460
}
5561

5662
let scope_data = &mir.source_scopes[scope];
5763
let parent_scope = if let Some(parent) = scope_data.parent_scope {
58-
make_mir_scope(cx, mir, fn_metadata, has_variables, debug_context, parent);
64+
make_mir_scope(cx, instance, mir, fn_dbg_scope, has_variables, debug_context, parent);
5965
debug_context.scopes[parent]
6066
} else {
6167
// The root is the function itself.
6268
let loc = cx.lookup_debug_loc(mir.span.lo());
6369
debug_context.scopes[scope] = DebugScope {
64-
scope_metadata: Some(fn_metadata),
70+
dbg_scope: Some(fn_dbg_scope),
71+
inlined_at: None,
6572
file_start_pos: loc.file.start_pos,
6673
file_end_pos: loc.file.end_pos,
6774
};
6875
return;
6976
};
7077

71-
if !has_variables.contains(scope) {
72-
// Do not create a DIScope if there are no variables
73-
// defined in this MIR Scope, to avoid debuginfo bloat.
78+
if !has_variables.contains(scope) && scope_data.inlined.is_none() {
79+
// Do not create a DIScope if there are no variables defined in this
80+
// MIR `SourceScope`, and it's not `inlined`, to avoid debuginfo bloat.
7481
debug_context.scopes[scope] = parent_scope;
7582
return;
7683
}
7784

7885
let loc = cx.lookup_debug_loc(scope_data.span.lo());
79-
let file_metadata = file_metadata(cx, &loc.file, debug_context.defining_crate);
86+
let file_metadata = file_metadata(cx, &loc.file);
8087

81-
let scope_metadata = unsafe {
82-
Some(llvm::LLVMRustDIBuilderCreateLexicalBlock(
83-
DIB(cx),
84-
parent_scope.scope_metadata.unwrap(),
85-
file_metadata,
86-
loc.line.unwrap_or(UNKNOWN_LINE_NUMBER),
87-
loc.col.unwrap_or(UNKNOWN_COLUMN_NUMBER),
88-
))
88+
let dbg_scope = match scope_data.inlined {
89+
Some((callee, _)) => {
90+
// FIXME(eddyb) this would be `self.monomorphize(&callee)`
91+
// if this is moved to `rustc_codegen_ssa::mir::debuginfo`.
92+
let callee = cx.tcx.subst_and_normalize_erasing_regions(
93+
instance.substs,
94+
ty::ParamEnv::reveal_all(),
95+
&callee,
96+
);
97+
let callee_fn_abi = FnAbi::of_instance(cx, callee, &[]);
98+
cx.dbg_scope_fn(callee, &callee_fn_abi, None)
99+
}
100+
None => unsafe {
101+
llvm::LLVMRustDIBuilderCreateLexicalBlock(
102+
DIB(cx),
103+
parent_scope.dbg_scope.unwrap(),
104+
file_metadata,
105+
loc.line.unwrap_or(UNKNOWN_LINE_NUMBER),
106+
loc.col.unwrap_or(UNKNOWN_COLUMN_NUMBER),
107+
)
108+
},
89109
};
110+
111+
let inlined_at = scope_data.inlined.map(|(_, callsite_span)| {
112+
// FIXME(eddyb) this doesn't account for the macro-related
113+
// `Span` fixups that `rustc_codegen_ssa::mir::debuginfo` does.
114+
let callsite_scope = parent_scope.adjust_dbg_scope_for_span(cx, callsite_span);
115+
cx.dbg_loc(callsite_scope, parent_scope.inlined_at, callsite_span)
116+
});
117+
90118
debug_context.scopes[scope] = DebugScope {
91-
scope_metadata,
119+
dbg_scope: Some(dbg_scope),
120+
inlined_at: inlined_at.or(parent_scope.inlined_at),
92121
file_start_pos: loc.file.start_pos,
93122
file_end_pos: loc.file.end_pos,
94123
};

compiler/rustc_codegen_llvm/src/debuginfo/doc.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
//! utilizing a cache. The way to get a shared metadata node when needed is
2929
//! thus to just call the corresponding function in this module:
3030
//!
31-
//! let file_metadata = file_metadata(crate_context, path);
31+
//! let file_metadata = file_metadata(cx, file);
3232
//!
3333
//! The function will take care of probing the cache for an existing node for
3434
//! that exact file path.

compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs

+8-13
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ use rustc_data_structures::fx::FxHashMap;
2626
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
2727
use rustc_fs_util::path_to_c_string;
2828
use rustc_hir::def::CtorKind;
29-
use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
29+
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
3030
use rustc_index::vec::{Idx, IndexVec};
3131
use rustc_middle::ich::NodeIdHashingMode;
3232
use rustc_middle::mir::interpret::truncate;
@@ -760,16 +760,12 @@ fn hex_encode(data: &[u8]) -> String {
760760
hex_string
761761
}
762762

763-
pub fn file_metadata(
764-
cx: &CodegenCx<'ll, '_>,
765-
source_file: &SourceFile,
766-
defining_crate: CrateNum,
767-
) -> &'ll DIFile {
768-
debug!("file_metadata: file_name: {}, defining_crate: {}", source_file.name, defining_crate);
763+
pub fn file_metadata(cx: &CodegenCx<'ll, '_>, source_file: &SourceFile) -> &'ll DIFile {
764+
debug!("file_metadata: file_name: {}", source_file.name);
769765

770766
let hash = Some(&source_file.src_hash);
771767
let file_name = Some(source_file.name.to_string());
772-
let directory = if defining_crate == LOCAL_CRATE {
768+
let directory = if source_file.is_real_file() && !source_file.is_imported() {
773769
Some(cx.sess().working_dir.0.to_string_lossy().to_string())
774770
} else {
775771
// If the path comes from an upstream crate we assume it has been made
@@ -1835,7 +1831,7 @@ impl<'tcx> VariantInfo<'_, 'tcx> {
18351831
if !span.is_dummy() {
18361832
let loc = cx.lookup_debug_loc(span.lo());
18371833
return Some(SourceInfo {
1838-
file: file_metadata(cx, &loc.file, def_id.krate),
1834+
file: file_metadata(cx, &loc.file),
18391835
line: loc.line.unwrap_or(UNKNOWN_LINE_NUMBER),
18401836
});
18411837
}
@@ -2474,7 +2470,7 @@ pub fn create_global_var_metadata(cx: &CodegenCx<'ll, '_>, def_id: DefId, global
24742470

24752471
let (file_metadata, line_number) = if !span.is_dummy() {
24762472
let loc = cx.lookup_debug_loc(span.lo());
2477-
(file_metadata(cx, &loc.file, LOCAL_CRATE), loc.line)
2473+
(file_metadata(cx, &loc.file), loc.line)
24782474
} else {
24792475
(unknown_file_metadata(cx), None)
24802476
};
@@ -2576,9 +2572,8 @@ pub fn create_vtable_metadata(cx: &CodegenCx<'ll, 'tcx>, ty: Ty<'tcx>, vtable: &
25762572
pub fn extend_scope_to_file(
25772573
cx: &CodegenCx<'ll, '_>,
25782574
scope_metadata: &'ll DIScope,
2579-
file: &rustc_span::SourceFile,
2580-
defining_crate: CrateNum,
2575+
file: &SourceFile,
25812576
) -> &'ll DILexicalBlock {
2582-
let file_metadata = file_metadata(cx, &file, defining_crate);
2577+
let file_metadata = file_metadata(cx, file);
25832578
unsafe { llvm::LLVMRustDIBuilderCreateLexicalBlockFile(DIB(cx), scope_metadata, file_metadata) }
25842579
}

0 commit comments

Comments
 (0)