]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs
Rollup merge of #105859 - compiler-errors:hr-lifetime-add, r=davidtwco
[rust.git] / compiler / rustc_codegen_llvm / src / debuginfo / create_scope_map.rs
1 use super::metadata::file_metadata;
2 use super::utils::DIB;
3 use rustc_codegen_ssa::mir::debuginfo::{DebugScope, FunctionDebugContext};
4 use rustc_codegen_ssa::traits::*;
5
6 use crate::common::CodegenCx;
7 use crate::llvm;
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;
13
14 use rustc_index::bit_set::BitSet;
15 use rustc_index::vec::Idx;
16
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>,
22     mir: &Body<'tcx>,
23     debug_context: &mut FunctionDebugContext<&'ll DIScope, &'ll DILocation>,
24 ) {
25     // Find all scopes with variables defined in them.
26     let variables = if cx.sess().opts.debuginfo == DebugInfo::Full {
27         let mut vars = BitSet::new_empty(mir.source_scopes.len());
28         // FIXME(eddyb) take into account that arguments always have debuginfo,
29         // irrespective of their name (assuming full debuginfo is enabled).
30         // NOTE(eddyb) actually, on second thought, those are always in the
31         // function scope, which always exists.
32         for var_debug_info in &mir.var_debug_info {
33             vars.insert(var_debug_info.source_info.scope);
34         }
35         Some(vars)
36     } else {
37         // Nothing to emit, of course.
38         None
39     };
40     let mut instantiated = BitSet::new_empty(mir.source_scopes.len());
41     // Instantiate all scopes.
42     for idx in 0..mir.source_scopes.len() {
43         let scope = SourceScope::new(idx);
44         make_mir_scope(cx, instance, mir, &variables, debug_context, &mut instantiated, scope);
45     }
46     assert!(instantiated.count() == mir.source_scopes.len());
47 }
48
49 fn make_mir_scope<'ll, 'tcx>(
50     cx: &CodegenCx<'ll, 'tcx>,
51     instance: Instance<'tcx>,
52     mir: &Body<'tcx>,
53     variables: &Option<BitSet<SourceScope>>,
54     debug_context: &mut FunctionDebugContext<&'ll DIScope, &'ll DILocation>,
55     instantiated: &mut BitSet<SourceScope>,
56     scope: SourceScope,
57 ) {
58     if instantiated.contains(scope) {
59         return;
60     }
61
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, variables, debug_context, instantiated, parent);
65         debug_context.scopes[parent]
66     } else {
67         // The root is the function itself.
68         let loc = cx.lookup_debug_loc(mir.span.lo());
69         debug_context.scopes[scope] = DebugScope {
70             file_start_pos: loc.file.start_pos,
71             file_end_pos: loc.file.end_pos,
72             ..debug_context.scopes[scope]
73         };
74         instantiated.insert(scope);
75         return;
76     };
77
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;
82         instantiated.insert(scope);
83         return;
84     }
85
86     let loc = cx.lookup_debug_loc(scope_data.span.lo());
87     let file_metadata = file_metadata(cx, &loc.file);
88
89     let dbg_scope = match scope_data.inlined {
90         Some((callee, _)) => {
91             // FIXME(eddyb) this would be `self.monomorphize(&callee)`
92             // if this is moved to `rustc_codegen_ssa::mir::debuginfo`.
93             let callee = cx.tcx.subst_and_normalize_erasing_regions(
94                 instance.substs,
95                 ty::ParamEnv::reveal_all(),
96                 callee,
97             );
98             let callee_fn_abi = cx.fn_abi_of_instance(callee, ty::List::empty());
99             cx.dbg_scope_fn(callee, callee_fn_abi, None)
100         }
101         None => unsafe {
102             llvm::LLVMRustDIBuilderCreateLexicalBlock(
103                 DIB(cx),
104                 parent_scope.dbg_scope,
105                 file_metadata,
106                 loc.line,
107                 loc.col,
108             )
109         },
110     };
111
112     let inlined_at = scope_data.inlined.map(|(_, callsite_span)| {
113         // FIXME(eddyb) this doesn't account for the macro-related
114         // `Span` fixups that `rustc_codegen_ssa::mir::debuginfo` does.
115         let callsite_scope = parent_scope.adjust_dbg_scope_for_span(cx, callsite_span);
116         cx.dbg_loc(callsite_scope, parent_scope.inlined_at, callsite_span)
117     });
118
119     debug_context.scopes[scope] = DebugScope {
120         dbg_scope,
121         inlined_at: inlined_at.or(parent_scope.inlined_at),
122         file_start_pos: loc.file.start_pos,
123         file_end_pos: loc.file.end_pos,
124     };
125     instantiated.insert(scope);
126 }