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 super::FunctionDebugContext
;
12 use super::metadata
::file_metadata
;
13 use super::utils
::{DIB, span_start}
;
16 use llvm
::debuginfo
::{DIScope, DISubprogram}
;
17 use common
::{CrateContext, FunctionContext}
;
18 use rustc
::mir
::{Mir, VisibilityScope}
;
25 use rustc_data_structures
::bitvec
::BitVector
;
26 use rustc_data_structures
::indexed_vec
::{Idx, IndexVec}
;
28 use syntax_pos
::BytePos
;
30 #[derive(Clone, Copy, Debug)]
31 pub struct MirDebugScope
{
32 pub scope_metadata
: DIScope
,
33 // Start and end offsets of the file to which this DIScope belongs.
34 // These are used to quickly determine whether some span refers to the same file.
35 pub file_start_pos
: BytePos
,
36 pub file_end_pos
: BytePos
,
40 pub fn is_valid(&self) -> bool
{
41 !self.scope_metadata
.is_null()
45 /// Produce DIScope DIEs for each MIR Scope which has variables defined in it.
46 /// If debuginfo is disabled, the returned vector is empty.
47 pub fn create_mir_scopes(fcx
: &FunctionContext
) -> IndexVec
<VisibilityScope
, MirDebugScope
> {
49 let null_scope
= MirDebugScope
{
50 scope_metadata
: ptr
::null_mut(),
51 file_start_pos
: BytePos(0),
52 file_end_pos
: BytePos(0)
54 let mut scopes
= IndexVec
::from_elem(null_scope
, &mir
.visibility_scopes
);
56 let fn_metadata
= match fcx
.debug_context
{
57 FunctionDebugContext
::RegularContext(box ref data
) => data
.fn_metadata
,
58 FunctionDebugContext
::DebugInfoDisabled
|
59 FunctionDebugContext
::FunctionWithoutDebugInfo
=> {
64 // Find all the scopes with variables defined in them.
65 let mut has_variables
= BitVector
::new(mir
.visibility_scopes
.len());
66 for var
in mir
.vars_iter() {
67 let decl
= &mir
.local_decls
[var
];
68 has_variables
.insert(decl
.source_info
.unwrap().scope
.index());
71 // Instantiate all scopes.
72 for idx
in 0..mir
.visibility_scopes
.len() {
73 let scope
= VisibilityScope
::new(idx
);
74 make_mir_scope(fcx
.ccx
, &mir
, &has_variables
, fn_metadata
, scope
, &mut scopes
);
80 fn make_mir_scope(ccx
: &CrateContext
,
82 has_variables
: &BitVector
,
83 fn_metadata
: DISubprogram
,
84 scope
: VisibilityScope
,
85 scopes
: &mut IndexVec
<VisibilityScope
, MirDebugScope
>) {
86 if scopes
[scope
].is_valid() {
90 let scope_data
= &mir
.visibility_scopes
[scope
];
91 let parent_scope
= if let Some(parent
) = scope_data
.parent_scope
{
92 make_mir_scope(ccx
, mir
, has_variables
, fn_metadata
, parent
, scopes
);
95 // The root is the function itself.
96 let loc
= span_start(ccx
, mir
.span
);
97 scopes
[scope
] = MirDebugScope
{
98 scope_metadata
: fn_metadata
,
99 file_start_pos
: loc
.file
.start_pos
,
100 file_end_pos
: loc
.file
.end_pos
,
105 if !has_variables
.contains(scope
.index()) {
106 // Do not create a DIScope if there are no variables
107 // defined in this MIR Scope, to avoid debuginfo bloat.
109 // However, we don't skip creating a nested scope if
110 // our parent is the root, because we might want to
111 // put arguments in the root and not have shadowing.
112 if parent_scope
.scope_metadata
!= fn_metadata
{
113 scopes
[scope
] = parent_scope
;
118 let loc
= span_start(ccx
, scope_data
.span
);
119 let file_metadata
= file_metadata(ccx
, &loc
.file
.name
, &loc
.file
.abs_path
);
120 let scope_metadata
= unsafe {
121 llvm
::LLVMRustDIBuilderCreateLexicalBlock(
123 parent_scope
.scope_metadata
,
126 loc
.col
.to_usize() as c_uint
)
128 scopes
[scope
] = MirDebugScope
{
129 scope_metadata
: scope_metadata
,
130 file_start_pos
: loc
.file
.start_pos
,
131 file_end_pos
: loc
.file
.end_pos
,