]> git.lizzy.rs Git - rust.git/blob - src/librustc_codegen_llvm/debuginfo/create_scope_map.rs
Rollup merge of #66808 - GuillaumeGomez:cleanup-err-code-3, r=Dylan-DPC
[rust.git] / src / librustc_codegen_llvm / debuginfo / create_scope_map.rs
1 use rustc_codegen_ssa::mir::debuginfo::{FunctionDebugContext, DebugScope};
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_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 pub fn compute_mir_scopes(
19     cx: &CodegenCx<'ll, '_>,
20     mir: &Body<'_>,
21     fn_metadata: &'ll DISubprogram,
22     debug_context: &mut FunctionDebugContext<&'ll DIScope>,
23 ) {
24     // Find all the scopes with variables defined in them.
25     let mut has_variables = BitSet::new_empty(mir.source_scopes.len());
26     // FIXME(eddyb) take into account that arguments always have debuginfo,
27     // irrespective of their name (assuming full debuginfo is enabled).
28     for var_debug_info in &mir.var_debug_info {
29         has_variables.insert(var_debug_info.source_info.scope);
30     }
31
32     // Instantiate all scopes.
33     for idx in 0..mir.source_scopes.len() {
34         let scope = SourceScope::new(idx);
35         make_mir_scope(cx, &mir, fn_metadata, &has_variables, debug_context, scope);
36     }
37 }
38
39 fn make_mir_scope(cx: &CodegenCx<'ll, '_>,
40                   mir: &Body<'_>,
41                   fn_metadata: &'ll DISubprogram,
42                   has_variables: &BitSet<SourceScope>,
43                   debug_context: &mut FunctionDebugContext<&'ll DISubprogram>,
44                   scope: SourceScope) {
45     if debug_context.scopes[scope].is_valid() {
46         return;
47     }
48
49     let scope_data = &mir.source_scopes[scope];
50     let parent_scope = if let Some(parent) = scope_data.parent_scope {
51         make_mir_scope(cx, mir, fn_metadata, has_variables, debug_context, parent);
52         debug_context.scopes[parent]
53     } else {
54         // The root is the function itself.
55         let loc = span_start(cx, mir.span);
56         debug_context.scopes[scope] = DebugScope {
57             scope_metadata: Some(fn_metadata),
58             file_start_pos: loc.file.start_pos,
59             file_end_pos: loc.file.end_pos,
60         };
61         return;
62     };
63
64     if !has_variables.contains(scope) {
65         // Do not create a DIScope if there are no variables
66         // defined in this MIR Scope, to avoid debuginfo bloat.
67
68         // However, we don't skip creating a nested scope if
69         // our parent is the root, because we might want to
70         // put arguments in the root and not have shadowing.
71         if parent_scope.scope_metadata.unwrap() != fn_metadata {
72             debug_context.scopes[scope] = parent_scope;
73             return;
74         }
75     }
76
77     let loc = span_start(cx, scope_data.span);
78     let file_metadata = file_metadata(cx,
79                                       &loc.file.name,
80                                       debug_context.defining_crate);
81
82     let scope_metadata = unsafe {
83         Some(llvm::LLVMRustDIBuilderCreateLexicalBlock(
84             DIB(cx),
85             parent_scope.scope_metadata.unwrap(),
86             file_metadata,
87             loc.line as c_uint,
88             loc.col.to_usize() as c_uint))
89     };
90     debug_context.scopes[scope] = DebugScope {
91         scope_metadata,
92         file_start_pos: loc.file.start_pos,
93         file_end_pos: loc.file.end_pos,
94     };
95 }