1 use super::metadata
::file_metadata
;
3 use rustc_codegen_ssa
::mir
::debuginfo
::{DebugScope, FunctionDebugContext}
;
4 use rustc_codegen_ssa
::traits
::*;
7 use crate::common
::CodegenCx
;
9 use crate::llvm
::debuginfo
::{DILocation, DIScope}
;
10 use rustc_middle
::mir
::{Body, SourceScope}
;
11 use rustc_middle
::ty
::layout
::FnAbiExt
;
12 use rustc_middle
::ty
::{self, Instance}
;
13 use rustc_session
::config
::DebugInfo
;
15 use rustc_index
::bit_set
::BitSet
;
16 use rustc_index
::vec
::Idx
;
18 /// 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`.
20 pub fn compute_mir_scopes(
21 cx
: &CodegenCx
<'ll
, 'tcx
>,
22 instance
: Instance
<'tcx
>,
24 fn_dbg_scope
: &'ll DIScope
,
25 debug_context
: &mut FunctionDebugContext
<&'ll DIScope
, &'ll DILocation
>,
27 // Find all the scopes with variables defined in them.
28 let mut has_variables
= BitSet
::new_empty(mir
.source_scopes
.len());
30 // Only consider variables when they're going to be emitted.
31 // FIXME(eddyb) don't even allocate `has_variables` otherwise.
32 if cx
.sess().opts
.debuginfo
== DebugInfo
::Full
{
33 // FIXME(eddyb) take into account that arguments always have debuginfo,
34 // irrespective of their name (assuming full debuginfo is enabled).
35 // NOTE(eddyb) actually, on second thought, those are always in the
36 // function scope, which always exists.
37 for var_debug_info
in &mir
.var_debug_info
{
38 has_variables
.insert(var_debug_info
.source_info
.scope
);
42 // Instantiate all scopes.
43 for idx
in 0..mir
.source_scopes
.len() {
44 let scope
= SourceScope
::new(idx
);
45 make_mir_scope(cx
, instance
, &mir
, fn_dbg_scope
, &has_variables
, debug_context
, scope
);
50 cx
: &CodegenCx
<'ll
, 'tcx
>,
51 instance
: Instance
<'tcx
>,
53 fn_dbg_scope
: &'ll DIScope
,
54 has_variables
: &BitSet
<SourceScope
>,
55 debug_context
: &mut FunctionDebugContext
<&'ll DIScope
, &'ll DILocation
>,
58 if debug_context
.scopes
[scope
].dbg_scope
.is_some() {
62 let scope_data
= &mir
.source_scopes
[scope
];
63 let parent_scope
= if let Some(parent
) = scope_data
.parent_scope
{
64 make_mir_scope(cx
, instance
, mir
, fn_dbg_scope
, has_variables
, debug_context
, parent
);
65 debug_context
.scopes
[parent
]
67 // The root is the function itself.
68 let loc
= cx
.lookup_debug_loc(mir
.span
.lo());
69 debug_context
.scopes
[scope
] = DebugScope
{
70 dbg_scope
: Some(fn_dbg_scope
),
72 file_start_pos
: loc
.file
.start_pos
,
73 file_end_pos
: loc
.file
.end_pos
,
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.
81 debug_context
.scopes
[scope
] = parent_scope
;
85 let loc
= cx
.lookup_debug_loc(scope_data
.span
.lo());
86 let file_metadata
= file_metadata(cx
, &loc
.file
);
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(
94 ty
::ParamEnv
::reveal_all(),
97 let callee_fn_abi
= FnAbi
::of_instance(cx
, callee
, &[]);
98 cx
.dbg_scope_fn(callee
, &callee_fn_abi
, None
)
101 llvm
::LLVMRustDIBuilderCreateLexicalBlock(
103 parent_scope
.dbg_scope
.unwrap(),
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
)
118 debug_context
.scopes
[scope
] = DebugScope
{
119 dbg_scope
: Some(dbg_scope
),
120 inlined_at
: inlined_at
.or(parent_scope
.inlined_at
),
121 file_start_pos
: loc
.file
.start_pos
,
122 file_end_pos
: loc
.file
.end_pos
,