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