1 use super::metadata
::file_metadata
;
3 use rustc_codegen_ssa
::mir
::debuginfo
::{DebugScope, FunctionDebugContext}
;
4 use rustc_codegen_ssa
::traits
::*;
6 use crate::common
::CodegenCx
;
8 use crate::llvm
::debuginfo
::{DILocation, DIScope}
;
9 use rustc_middle
::mir
::{Body, SourceScope}
;
10 use rustc_middle
::ty
::layout
::FnAbiOf
;
11 use rustc_middle
::ty
::{self, Instance}
;
12 use rustc_session
::config
::DebugInfo
;
14 use rustc_index
::bit_set
::BitSet
;
15 use rustc_index
::vec
::Idx
;
17 /// Produces DIScope DIEs for each MIR Scope which has variables defined in it.
18 // FIXME(eddyb) almost all of this should be in `rustc_codegen_ssa::mir::debuginfo`.
19 pub fn compute_mir_scopes
<'ll
, 'tcx
>(
20 cx
: &CodegenCx
<'ll
, 'tcx
>,
21 instance
: Instance
<'tcx
>,
23 fn_dbg_scope
: &'ll DIScope
,
24 debug_context
: &mut FunctionDebugContext
<&'ll DIScope
, &'ll DILocation
>,
26 // Find all scopes with variables defined in them.
27 let variables
= if cx
.sess().opts
.debuginfo
== DebugInfo
::Full
{
28 let mut vars
= BitSet
::new_empty(mir
.source_scopes
.len());
29 // FIXME(eddyb) take into account that arguments always have debuginfo,
30 // irrespective of their name (assuming full debuginfo is enabled).
31 // NOTE(eddyb) actually, on second thought, those are always in the
32 // function scope, which always exists.
33 for var_debug_info
in &mir
.var_debug_info
{
34 vars
.insert(var_debug_info
.source_info
.scope
);
38 // Nothing to emit, of course.
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
, &variables
, debug_context
, scope
);
49 fn make_mir_scope
<'ll
, 'tcx
>(
50 cx
: &CodegenCx
<'ll
, 'tcx
>,
51 instance
: Instance
<'tcx
>,
53 fn_dbg_scope
: &'ll DIScope
,
54 variables
: &Option
<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
, 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 let Some(vars
) = variables
&& !vars
.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
= cx
.fn_abi_of_instance(callee
, ty
::List
::empty());
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
,