]>
Commit | Line | Data |
---|---|---|
6a06907d | 1 | use super::metadata::file_metadata; |
ba9703b0 | 2 | use super::utils::DIB; |
dfeec247 | 3 | use rustc_codegen_ssa::mir::debuginfo::{DebugScope, FunctionDebugContext}; |
ba9703b0 | 4 | use rustc_codegen_ssa::traits::*; |
d9579d0f | 5 | |
dfeec247 | 6 | use crate::common::CodegenCx; |
9fa01778 | 7 | use crate::llvm; |
29967ef6 | 8 | use crate::llvm::debuginfo::{DILocation, DIScope}; |
ba9703b0 | 9 | use rustc_middle::mir::{Body, SourceScope}; |
c295e0f8 | 10 | use rustc_middle::ty::layout::FnAbiOf; |
29967ef6 | 11 | use rustc_middle::ty::{self, Instance}; |
ba9703b0 | 12 | use rustc_session::config::DebugInfo; |
e9174d1e | 13 | |
e74abb32 | 14 | use rustc_index::bit_set::BitSet; |
49aad941 | 15 | use rustc_index::Idx; |
d9579d0f | 16 | |
9fa01778 | 17 | /// Produces DIScope DIEs for each MIR Scope which has variables defined in it. |
29967ef6 | 18 | // FIXME(eddyb) almost all of this should be in `rustc_codegen_ssa::mir::debuginfo`. |
a2a8927a | 19 | pub fn compute_mir_scopes<'ll, 'tcx>( |
29967ef6 XL |
20 | cx: &CodegenCx<'ll, 'tcx>, |
21 | instance: Instance<'tcx>, | |
22 | mir: &Body<'tcx>, | |
29967ef6 | 23 | debug_context: &mut FunctionDebugContext<&'ll DIScope, &'ll DILocation>, |
e74abb32 | 24 | ) { |
5e7ed085 FG |
25 | // Find all scopes with variables defined in them. |
26 | let variables = if cx.sess().opts.debuginfo == DebugInfo::Full { | |
27 | let mut vars = BitSet::new_empty(mir.source_scopes.len()); | |
ba9703b0 XL |
28 | // FIXME(eddyb) take into account that arguments always have debuginfo, |
29 | // irrespective of their name (assuming full debuginfo is enabled). | |
30 | // NOTE(eddyb) actually, on second thought, those are always in the | |
31 | // function scope, which always exists. | |
32 | for var_debug_info in &mir.var_debug_info { | |
5e7ed085 | 33 | vars.insert(var_debug_info.source_info.scope); |
ba9703b0 | 34 | } |
5e7ed085 FG |
35 | Some(vars) |
36 | } else { | |
37 | // Nothing to emit, of course. | |
38 | None | |
39 | }; | |
04454e1e | 40 | let mut instantiated = BitSet::new_empty(mir.source_scopes.len()); |
a7813a04 | 41 | // Instantiate all scopes. |
94b46f34 XL |
42 | for idx in 0..mir.source_scopes.len() { |
43 | let scope = SourceScope::new(idx); | |
04454e1e | 44 | make_mir_scope(cx, instance, mir, &variables, debug_context, &mut instantiated, scope); |
a7813a04 | 45 | } |
04454e1e | 46 | assert!(instantiated.count() == mir.source_scopes.len()); |
a7813a04 XL |
47 | } |
48 | ||
a2a8927a | 49 | fn make_mir_scope<'ll, 'tcx>( |
29967ef6 XL |
50 | cx: &CodegenCx<'ll, 'tcx>, |
51 | instance: Instance<'tcx>, | |
52 | mir: &Body<'tcx>, | |
5e7ed085 | 53 | variables: &Option<BitSet<SourceScope>>, |
29967ef6 | 54 | debug_context: &mut FunctionDebugContext<&'ll DIScope, &'ll DILocation>, |
04454e1e | 55 | instantiated: &mut BitSet<SourceScope>, |
dfeec247 XL |
56 | scope: SourceScope, |
57 | ) { | |
04454e1e | 58 | if instantiated.contains(scope) { |
a7813a04 XL |
59 | return; |
60 | } | |
61 | ||
94b46f34 | 62 | let scope_data = &mir.source_scopes[scope]; |
a7813a04 | 63 | let parent_scope = if let Some(parent) = scope_data.parent_scope { |
04454e1e | 64 | make_mir_scope(cx, instance, mir, variables, debug_context, instantiated, parent); |
e74abb32 | 65 | debug_context.scopes[parent] |
a7813a04 XL |
66 | } else { |
67 | // The root is the function itself. | |
ba9703b0 | 68 | let loc = cx.lookup_debug_loc(mir.span.lo()); |
e74abb32 | 69 | debug_context.scopes[scope] = DebugScope { |
9e0c209e SL |
70 | file_start_pos: loc.file.start_pos, |
71 | file_end_pos: loc.file.end_pos, | |
04454e1e | 72 | ..debug_context.scopes[scope] |
9e0c209e | 73 | }; |
04454e1e | 74 | instantiated.insert(scope); |
a7813a04 XL |
75 | return; |
76 | }; | |
77 | ||
5e7ed085 | 78 | if let Some(vars) = variables && !vars.contains(scope) && scope_data.inlined.is_none() { |
29967ef6 XL |
79 | // Do not create a DIScope if there are no variables defined in this |
80 | // MIR `SourceScope`, and it's not `inlined`, to avoid debuginfo bloat. | |
74b04a01 | 81 | debug_context.scopes[scope] = parent_scope; |
04454e1e | 82 | instantiated.insert(scope); |
74b04a01 | 83 | return; |
a7813a04 XL |
84 | } |
85 | ||
ba9703b0 | 86 | let loc = cx.lookup_debug_loc(scope_data.span.lo()); |
29967ef6 | 87 | let file_metadata = file_metadata(cx, &loc.file); |
7cac9316 | 88 | |
29967ef6 XL |
89 | let dbg_scope = match scope_data.inlined { |
90 | Some((callee, _)) => { | |
91 | // FIXME(eddyb) this would be `self.monomorphize(&callee)` | |
92 | // if this is moved to `rustc_codegen_ssa::mir::debuginfo`. | |
93 | let callee = cx.tcx.subst_and_normalize_erasing_regions( | |
94 | instance.substs, | |
95 | ty::ParamEnv::reveal_all(), | |
49aad941 | 96 | ty::EarlyBinder(callee), |
29967ef6 | 97 | ); |
c295e0f8 XL |
98 | let callee_fn_abi = cx.fn_abi_of_instance(callee, ty::List::empty()); |
99 | cx.dbg_scope_fn(callee, callee_fn_abi, None) | |
29967ef6 XL |
100 | } |
101 | None => unsafe { | |
102 | llvm::LLVMRustDIBuilderCreateLexicalBlock( | |
103 | DIB(cx), | |
04454e1e | 104 | parent_scope.dbg_scope, |
29967ef6 | 105 | file_metadata, |
6a06907d XL |
106 | loc.line, |
107 | loc.col, | |
29967ef6 XL |
108 | ) |
109 | }, | |
a7813a04 | 110 | }; |
29967ef6 XL |
111 | |
112 | let inlined_at = scope_data.inlined.map(|(_, callsite_span)| { | |
113 | // FIXME(eddyb) this doesn't account for the macro-related | |
114 | // `Span` fixups that `rustc_codegen_ssa::mir::debuginfo` does. | |
115 | let callsite_scope = parent_scope.adjust_dbg_scope_for_span(cx, callsite_span); | |
116 | cx.dbg_loc(callsite_scope, parent_scope.inlined_at, callsite_span) | |
117 | }); | |
118 | ||
e74abb32 | 119 | debug_context.scopes[scope] = DebugScope { |
04454e1e | 120 | dbg_scope, |
29967ef6 | 121 | inlined_at: inlined_at.or(parent_scope.inlined_at), |
9e0c209e SL |
122 | file_start_pos: loc.file.start_pos, |
123 | file_end_pos: loc.file.end_pos, | |
d9579d0f | 124 | }; |
04454e1e | 125 | instantiated.insert(scope); |
92a42be0 | 126 | } |