1 use rustc_codegen_ssa::debuginfo::{FunctionDebugContext, FunctionDebugContextData, MirDebugScope};
2 use super::metadata::file_metadata;
3 use super::utils::{DIB, span_start};
6 use crate::llvm::debuginfo::{DIScope, DISubprogram};
7 use crate::common::CodegenCx;
8 use rustc::mir::{Body, SourceScope};
14 use rustc_data_structures::bit_set::BitSet;
15 use rustc_data_structures::indexed_vec::{Idx, IndexVec};
17 use syntax_pos::BytePos;
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, '_>,
24 debug_context: &FunctionDebugContext<&'ll DISubprogram>,
25 ) -> IndexVec<SourceScope, MirDebugScope<&'ll DIScope>> {
26 let null_scope = MirDebugScope {
28 file_start_pos: BytePos(0),
29 file_end_pos: BytePos(0)
31 let mut scopes = IndexVec::from_elem(null_scope, &mir.source_scopes);
33 let debug_context = match *debug_context {
34 FunctionDebugContext::RegularContext(ref data) => data,
35 FunctionDebugContext::DebugInfoDisabled |
36 FunctionDebugContext::FunctionWithoutDebugInfo => {
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);
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);
57 fn make_mir_scope(cx: &CodegenCx<'ll, '_>,
59 has_variables: &BitSet<SourceScope>,
60 debug_context: &FunctionDebugContextData<&'ll DISubprogram>,
62 scopes: &mut IndexVec<SourceScope, MirDebugScope<&'ll DIScope>>) {
63 if scopes[scope].is_valid() {
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);
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,
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.
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;
95 let loc = span_start(cx, scope_data.span);
96 let file_metadata = file_metadata(cx,
98 debug_context.defining_crate);
100 let scope_metadata = unsafe {
101 Some(llvm::LLVMRustDIBuilderCreateLexicalBlock(
103 parent_scope.scope_metadata.unwrap(),
106 loc.col.to_usize() as c_uint))
108 scopes[scope] = MirDebugScope {
110 file_start_pos: loc.file.start_pos,
111 file_end_pos: loc.file.end_pos,