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.
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.
11 use rustc_codegen_ssa::debuginfo::{FunctionDebugContext, FunctionDebugContextData, MirDebugScope};
12 use super::metadata::file_metadata;
13 use super::utils::{DIB, span_start};
16 use llvm::debuginfo::{DIScope, DISubprogram};
17 use common::CodegenCx;
18 use rustc::mir::{Mir, SourceScope};
24 use rustc_data_structures::bit_set::BitSet;
25 use rustc_data_structures::indexed_vec::{Idx, IndexVec};
27 use syntax_pos::BytePos;
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, '_>,
34 debug_context: &FunctionDebugContext<&'ll DISubprogram>,
35 ) -> IndexVec<SourceScope, MirDebugScope<&'ll DIScope>> {
36 let null_scope = MirDebugScope {
38 file_start_pos: BytePos(0),
39 file_end_pos: BytePos(0)
41 let mut scopes = IndexVec::from_elem(null_scope, &mir.source_scopes);
43 let debug_context = match *debug_context {
44 FunctionDebugContext::RegularContext(ref data) => data,
45 FunctionDebugContext::DebugInfoDisabled |
46 FunctionDebugContext::FunctionWithoutDebugInfo => {
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);
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);
67 fn make_mir_scope(cx: &CodegenCx<'ll, '_>,
69 has_variables: &BitSet<SourceScope>,
70 debug_context: &FunctionDebugContextData<&'ll DISubprogram>,
72 scopes: &mut IndexVec<SourceScope, MirDebugScope<&'ll DIScope>>) {
73 if scopes[scope].is_valid() {
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);
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,
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.
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;
105 let loc = span_start(cx, scope_data.span);
106 let file_metadata = file_metadata(cx,
108 debug_context.defining_crate);
110 let scope_metadata = unsafe {
111 Some(llvm::LLVMRustDIBuilderCreateLexicalBlock(
113 parent_scope.scope_metadata.unwrap(),
116 loc.col.to_usize() as c_uint))
118 scopes[scope] = MirDebugScope {
120 file_start_pos: loc.file.start_pos,
121 file_end_pos: loc.file.end_pos,