]> git.lizzy.rs Git - rust.git/blob - src/librustc_codegen_llvm/debuginfo/create_scope_map.rs
Rollup merge of #61273 - RalfJung:maybe-uninit, r=Centril
[rust.git] / src / librustc_codegen_llvm / debuginfo / create_scope_map.rs
1 use rustc_codegen_ssa::debuginfo::{FunctionDebugContext, FunctionDebugContextData, MirDebugScope};
2 use super::metadata::file_metadata;
3 use super::utils::{DIB, span_start};
4
5 use crate::llvm;
6 use crate::llvm::debuginfo::{DIScope, DISubprogram};
7 use crate::common::CodegenCx;
8 use rustc::mir::{Body, SourceScope};
9
10 use libc::c_uint;
11
12 use syntax_pos::Pos;
13
14 use rustc_data_structures::bit_set::BitSet;
15 use rustc_data_structures::indexed_vec::{Idx, IndexVec};
16
17 use syntax_pos::BytePos;
18
19 /// Produces DIScope DIEs for each MIR Scope which has variables defined in it.
20 /// If debuginfo is disabled, the returned vector is empty.
21 pub fn create_mir_scopes(
22     cx: &CodegenCx<'ll, '_>,
23     mir: &Body<'_>,
24     debug_context: &FunctionDebugContext<&'ll DISubprogram>,
25 ) -> IndexVec<SourceScope, MirDebugScope<&'ll DIScope>> {
26     let null_scope = MirDebugScope {
27         scope_metadata: None,
28         file_start_pos: BytePos(0),
29         file_end_pos: BytePos(0)
30     };
31     let mut scopes = IndexVec::from_elem(null_scope, &mir.source_scopes);
32
33     let debug_context = match *debug_context {
34         FunctionDebugContext::RegularContext(ref data) => data,
35         FunctionDebugContext::DebugInfoDisabled |
36         FunctionDebugContext::FunctionWithoutDebugInfo => {
37             return scopes;
38         }
39     };
40
41     // Find all the scopes with variables defined in them.
42     let mut has_variables = BitSet::new_empty(mir.source_scopes.len());
43     for var in mir.vars_iter() {
44         let decl = &mir.local_decls[var];
45         has_variables.insert(decl.visibility_scope);
46     }
47
48     // Instantiate all scopes.
49     for idx in 0..mir.source_scopes.len() {
50         let scope = SourceScope::new(idx);
51         make_mir_scope(cx, &mir, &has_variables, debug_context, scope, &mut scopes);
52     }
53
54     scopes
55 }
56
57 fn make_mir_scope(cx: &CodegenCx<'ll, '_>,
58                   mir: &Body<'_>,
59                   has_variables: &BitSet<SourceScope>,
60                   debug_context: &FunctionDebugContextData<&'ll DISubprogram>,
61                   scope: SourceScope,
62                   scopes: &mut IndexVec<SourceScope, MirDebugScope<&'ll DIScope>>) {
63     if scopes[scope].is_valid() {
64         return;
65     }
66
67     let scope_data = &mir.source_scopes[scope];
68     let parent_scope = if let Some(parent) = scope_data.parent_scope {
69         make_mir_scope(cx, mir, has_variables, debug_context, parent, scopes);
70         scopes[parent]
71     } else {
72         // The root is the function itself.
73         let loc = span_start(cx, mir.span);
74         scopes[scope] = MirDebugScope {
75             scope_metadata: Some(debug_context.fn_metadata),
76             file_start_pos: loc.file.start_pos,
77             file_end_pos: loc.file.end_pos,
78         };
79         return;
80     };
81
82     if !has_variables.contains(scope) {
83         // Do not create a DIScope if there are no variables
84         // defined in this MIR Scope, to avoid debuginfo bloat.
85
86         // However, we don't skip creating a nested scope if
87         // our parent is the root, because we might want to
88         // put arguments in the root and not have shadowing.
89         if parent_scope.scope_metadata.unwrap() != debug_context.fn_metadata {
90             scopes[scope] = parent_scope;
91             return;
92         }
93     }
94
95     let loc = span_start(cx, scope_data.span);
96     let file_metadata = file_metadata(cx,
97                                       &loc.file.name,
98                                       debug_context.defining_crate);
99
100     let scope_metadata = unsafe {
101         Some(llvm::LLVMRustDIBuilderCreateLexicalBlock(
102             DIB(cx),
103             parent_scope.scope_metadata.unwrap(),
104             file_metadata,
105             loc.line as c_uint,
106             loc.col.to_usize() as c_uint))
107     };
108     scopes[scope] = MirDebugScope {
109         scope_metadata,
110         file_start_pos: loc.file.start_pos,
111         file_end_pos: loc.file.end_pos,
112     };
113 }