Skip to content

Commit ce8d4a2

Browse files
committed
trans: initial implementation of MIR debuginfo.
1 parent f680c62 commit ce8d4a2

File tree

11 files changed

+289
-123
lines changed

11 files changed

+289
-123
lines changed

src/librustc_trans/base.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1276,7 +1276,7 @@ pub fn alloca(cx: Block, ty: Type, name: &str) -> ValueRef {
12761276
return llvm::LLVMGetUndef(ty.ptr_to().to_ref());
12771277
}
12781278
}
1279-
debuginfo::clear_source_location(cx.fcx);
1279+
DebugLoc::None.apply(cx.fcx);
12801280
Alloca(cx, ty, name)
12811281
}
12821282

@@ -1739,7 +1739,7 @@ impl<'blk, 'tcx> FunctionContext<'blk, 'tcx> {
17391739

17401740
self.build_return_block(ret_cx, ret_debug_loc);
17411741

1742-
debuginfo::clear_source_location(self);
1742+
DebugLoc::None.apply(self);
17431743
self.cleanup();
17441744
}
17451745

src/librustc_trans/controlflow.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -167,11 +167,11 @@ pub fn trans_if<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
167167
if cv == 1 {
168168
// if true { .. } [else { .. }]
169169
bcx = trans_block(bcx, &thn, dest);
170-
debuginfo::clear_source_location(bcx.fcx);
170+
DebugLoc::None.apply(bcx.fcx);
171171
} else {
172172
if let Some(elexpr) = els {
173173
bcx = expr::trans_into(bcx, &elexpr, dest);
174-
debuginfo::clear_source_location(bcx.fcx);
174+
DebugLoc::None.apply(bcx.fcx);
175175
}
176176
}
177177

@@ -181,7 +181,7 @@ pub fn trans_if<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
181181
let name = format!("then-block-{}-", thn.id);
182182
let then_bcx_in = bcx.fcx.new_id_block(&name[..], thn.id);
183183
let then_bcx_out = trans_block(then_bcx_in, &thn, dest);
184-
debuginfo::clear_source_location(bcx.fcx);
184+
DebugLoc::None.apply(bcx.fcx);
185185

186186
let cond_source_loc = cond.debug_loc();
187187

@@ -204,7 +204,7 @@ pub fn trans_if<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
204204

205205
// Clear the source location because it is still set to whatever has been translated
206206
// right before.
207-
debuginfo::clear_source_location(next_bcx.fcx);
207+
DebugLoc::None.apply(next_bcx.fcx);
208208

209209
next_bcx
210210
}

src/librustc_trans/debuginfo/create_scope_map.rs

Lines changed: 77 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,24 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
use super::FunctionDebugContext;
1112
use super::metadata::file_metadata;
12-
use super::utils::DIB;
13+
use super::utils::{DIB, span_start};
1314

1415
use llvm;
1516
use llvm::debuginfo::{DIScope, DISubprogram};
16-
use common::CrateContext;
17+
use common::{CrateContext, FunctionContext};
1718
use rustc::hir::pat_util;
19+
use rustc::mir::repr::{Mir, ScopeId};
1820
use rustc::util::nodemap::NodeMap;
1921

2022
use libc::c_uint;
23+
use std::ptr;
24+
2125
use syntax::codemap::{Span, Pos};
2226
use syntax::{ast, codemap};
2327

28+
use rustc_data_structures::bitvec::BitVector;
2429
use rustc::hir::{self, PatKind};
2530

2631
// This procedure builds the *scope map* for a given function, which maps any
@@ -65,6 +70,74 @@ pub fn create_scope_map(cx: &CrateContext,
6570
return scope_map;
6671
}
6772

73+
/// Produce DIScope DIEs for each MIR Scope which has variables defined in it.
74+
/// If debuginfo is disabled, the returned vector is empty.
75+
pub fn create_mir_scopes(fcx: &FunctionContext) -> Vec<DIScope> {
76+
let mir = fcx.mir.clone().expect("create_mir_scopes: missing MIR for fn");
77+
let mut scopes = vec![ptr::null_mut(); mir.scopes.len()];
78+
79+
let fn_metadata = match fcx.debug_context {
80+
FunctionDebugContext::RegularContext(box ref data) => data.fn_metadata,
81+
FunctionDebugContext::DebugInfoDisabled |
82+
FunctionDebugContext::FunctionWithoutDebugInfo => {
83+
return scopes;
84+
}
85+
};
86+
87+
// Find all the scopes with variables defined in them.
88+
let mut has_variables = BitVector::new(mir.scopes.len());
89+
for var in &mir.var_decls {
90+
has_variables.insert(var.scope.index());
91+
}
92+
93+
// Instantiate all scopes.
94+
for idx in 0..mir.scopes.len() {
95+
let scope = ScopeId::new(idx);
96+
make_mir_scope(fcx.ccx, &mir, &has_variables, fn_metadata, scope, &mut scopes);
97+
}
98+
99+
scopes
100+
}
101+
102+
fn make_mir_scope(ccx: &CrateContext,
103+
mir: &Mir,
104+
has_variables: &BitVector,
105+
fn_metadata: DISubprogram,
106+
scope: ScopeId,
107+
scopes: &mut [DIScope]) {
108+
let idx = scope.index();
109+
if !scopes[idx].is_null() {
110+
return;
111+
}
112+
113+
let scope_data = &mir.scopes[scope];
114+
let parent_scope = if let Some(parent) = scope_data.parent_scope {
115+
make_mir_scope(ccx, mir, has_variables, fn_metadata, parent, scopes);
116+
scopes[parent.index()]
117+
} else {
118+
// The root is the function itself.
119+
scopes[idx] = fn_metadata;
120+
return;
121+
};
122+
123+
scopes[idx] = if !has_variables.contains(idx) {
124+
// Do not create a DIScope if there are no variables
125+
// defined in this MIR Scope, to avoid debuginfo bloat.
126+
parent_scope
127+
} else {
128+
let loc = span_start(ccx, scope_data.span);
129+
let file_metadata = file_metadata(ccx, &loc.file.name);
130+
unsafe {
131+
llvm::LLVMDIBuilderCreateLexicalBlock(
132+
DIB(ccx),
133+
parent_scope,
134+
file_metadata,
135+
loc.line as c_uint,
136+
loc.col.to_usize() as c_uint)
137+
}
138+
};
139+
}
140+
68141
// local helper functions for walking the AST.
69142
fn with_new_scope<F>(cx: &CrateContext,
70143
scope_span: Span,
@@ -74,7 +147,7 @@ fn with_new_scope<F>(cx: &CrateContext,
74147
F: FnOnce(&CrateContext, &mut Vec<ScopeStackEntry>, &mut NodeMap<DIScope>),
75148
{
76149
// Create a new lexical scope and push it onto the stack
77-
let loc = cx.sess().codemap().lookup_char_pos(scope_span.lo);
150+
let loc = span_start(cx, scope_span);
78151
let file_metadata = file_metadata(cx, &loc.file.name);
79152
let parent_scope = scope_stack.last().unwrap().scope_metadata;
80153

@@ -199,7 +272,7 @@ fn walk_pattern(cx: &CrateContext,
199272

200273
if need_new_scope {
201274
// Create a new lexical scope and push it onto the stack
202-
let loc = cx.sess().codemap().lookup_char_pos(pat.span.lo);
275+
let loc = span_start(cx, pat.span);
203276
let file_metadata = file_metadata(cx, &loc.file.name);
204277
let parent_scope = scope_stack.last().unwrap().scope_metadata;
205278

src/librustc_trans/debuginfo/mod.rs

Lines changed: 22 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use self::namespace::mangled_name_of_item;
2020
use self::type_names::compute_debuginfo_type_name;
2121
use self::metadata::{type_metadata, diverging_type_metadata};
2222
use self::metadata::{file_metadata, scope_metadata, TypeMap, compile_unit_metadata};
23-
use self::source_loc::InternalDebugLocation;
23+
use self::source_loc::InternalDebugLocation::{self, UnknownLocation};
2424

2525
use llvm;
2626
use llvm::{ModuleRef, ContextRef, ValueRef};
@@ -32,7 +32,7 @@ use rustc::ty::subst::Substs;
3232
use rustc::hir;
3333

3434
use abi::Abi;
35-
use common::{NodeIdAndSpan, CrateContext, FunctionContext, Block};
35+
use common::{NodeIdAndSpan, CrateContext, FunctionContext, Block, BlockAndBuilder};
3636
use monomorphize::Instance;
3737
use rustc::ty::{self, Ty};
3838
use session::config::{self, FullDebugInfo, LimitedDebugInfo, NoDebugInfo};
@@ -55,8 +55,7 @@ mod metadata;
5555
mod create_scope_map;
5656
mod source_loc;
5757

58-
pub use self::source_loc::set_source_location;
59-
pub use self::source_loc::clear_source_location;
58+
pub use self::create_scope_map::create_mir_scopes;
6059
pub use self::source_loc::start_emitting_source_locations;
6160
pub use self::source_loc::get_cleanup_debug_loc_for_ast_node;
6261
pub use self::source_loc::with_source_location_override;
@@ -218,7 +217,7 @@ pub fn empty_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>)
218217
}
219218

220219
// Clear the debug location so we don't assign them in the function prelude.
221-
source_loc::set_debug_location(cx, InternalDebugLocation::UnknownLocation);
220+
source_loc::set_debug_location(cx, None, UnknownLocation);
222221
FunctionDebugContext::FunctionWithoutDebugInfo
223222
}
224223

@@ -239,7 +238,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
239238

240239
// Clear the debug location so we don't assign them in the function prelude.
241240
// Do this here already, in case we do an early exit from this function.
242-
source_loc::set_debug_location(cx, InternalDebugLocation::UnknownLocation);
241+
source_loc::set_debug_location(cx, None, UnknownLocation);
243242

244243
// This can be the case for functions inlined from another crate
245244
let (containing_scope, span) = get_namespace_and_span_for_item(cx, instance.def);
@@ -425,13 +424,13 @@ pub fn fill_scope_map_for_function<'a, 'tcx>(fcx: &FunctionContext<'a, 'tcx>,
425424
}
426425
}
427426

428-
fn declare_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
429-
variable_name: ast::Name,
430-
variable_type: Ty<'tcx>,
431-
scope_metadata: DIScope,
432-
variable_access: VariableAccess,
433-
variable_kind: VariableKind,
434-
span: Span) {
427+
pub fn declare_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
428+
variable_name: ast::Name,
429+
variable_type: Ty<'tcx>,
430+
scope_metadata: DIScope,
431+
variable_access: VariableAccess,
432+
variable_kind: VariableKind,
433+
span: Span) {
435434
let cx: &CrateContext = bcx.ccx();
436435

437436
let filename = span_start(cx, span).file.name.clone();
@@ -465,9 +464,8 @@ fn declare_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
465464
address_operations.len() as c_uint,
466465
argument_index)
467466
};
468-
source_loc::set_debug_location(cx, InternalDebugLocation::new(scope_metadata,
469-
loc.line,
470-
loc.col.to_usize()));
467+
source_loc::set_debug_location(cx, None,
468+
InternalDebugLocation::new(scope_metadata, loc.line, loc.col.to_usize()));
471469
unsafe {
472470
let debug_loc = llvm::LLVMGetCurrentDebugLocation(cx.raw_builder());
473471
let instr = llvm::LLVMDIBuilderInsertDeclareAtEnd(
@@ -491,7 +489,7 @@ fn declare_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
491489
.get_ref(span)
492490
.source_locations_enabled
493491
.get());
494-
source_loc::set_debug_location(cx, InternalDebugLocation::UnknownLocation);
492+
source_loc::set_debug_location(cx, None, UnknownLocation);
495493
}
496494
_ => { /* nothing to do */ }
497495
}
@@ -500,19 +498,17 @@ fn declare_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
500498
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
501499
pub enum DebugLoc {
502500
At(ast::NodeId, Span),
501+
ScopeAt(DIScope, Span),
503502
None
504503
}
505504

506505
impl DebugLoc {
507-
pub fn apply(&self, fcx: &FunctionContext) {
508-
match *self {
509-
DebugLoc::At(node_id, span) => {
510-
source_loc::set_source_location(fcx, node_id, span);
511-
}
512-
DebugLoc::None => {
513-
source_loc::clear_source_location(fcx);
514-
}
515-
}
506+
pub fn apply(self, fcx: &FunctionContext) {
507+
source_loc::set_source_location(fcx, None, self);
508+
}
509+
510+
pub fn apply_to_bcx(self, bcx: &BlockAndBuilder) {
511+
source_loc::set_source_location(bcx.fcx(), Some(bcx), self);
516512
}
517513
}
518514

0 commit comments

Comments
 (0)