Skip to content

Commit 659f420

Browse files
committed
Fix debug line number info for macro expansions.
Macro expansions result in code tagged with completely different debug locations than the surrounding expressions. This wrecks havoc on debugger's ability the step over source lines. This change fixes the problem by tagging expanded code as "inlined" at the macro expansion site, which allows the debugger to sort it out. Note that only the outermost expansion is currently handled, stepping into a macro will still result in stepping craziness.
1 parent a0b4e67 commit 659f420

File tree

10 files changed

+286
-62
lines changed

10 files changed

+286
-62
lines changed

src/librustc/middle/region.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ impl CodeExtent {
237237
// (This is the special case aluded to in the
238238
// doc-comment for this method)
239239
let stmt_span = blk.stmts[r.first_statement_index as usize].span;
240-
Some(Span { lo: stmt_span.hi, ..blk.span })
240+
Some(Span { lo: stmt_span.hi, hi: blk.span.hi, expn_id: stmt_span.expn_id })
241241
}
242242
}
243243
}

src/librustc_llvm/ffi.rs

+7
Original file line numberDiff line numberDiff line change
@@ -637,6 +637,8 @@ extern {
637637
pub fn LLVMAddNamedMetadataOperand(M: ModuleRef,
638638
Str: *const c_char,
639639
Val: ValueRef);
640+
pub fn LLVMRustMetadataAsValue(context: ContextRef, metadata: MetadataRef) -> ValueRef;
641+
pub fn LLVMRustValueAsMetadata(value: ValueRef) -> MetadataRef;
640642

641643
/* Operations on scalar constants */
642644
pub fn LLVMConstInt(IntTy: TypeRef, N: c_ulonglong, SignExtend: Bool)
@@ -1796,6 +1798,11 @@ extern {
17961798
Col: c_uint)
17971799
-> DILexicalBlock;
17981800

1801+
pub fn LLVMRustDIBuilderCreateLexicalBlockFile(Builder: DIBuilderRef,
1802+
Scope: DIScope,
1803+
File: DIFile)
1804+
-> DILexicalBlock;
1805+
17991806
pub fn LLVMRustDIBuilderCreateStaticVariable(Builder: DIBuilderRef,
18001807
Context: DIScope,
18011808
Name: *const c_char,

src/librustc_trans/debuginfo/create_scope_map.rs

+38-8
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ use rustc_data_structures::bitvec::BitVector;
2929
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
3030
use rustc::hir::{self, PatKind};
3131

32+
use syntax_pos::BytePos;
33+
3234
// This procedure builds the *scope map* for a given function, which maps any
3335
// given ast::NodeId in the function's AST to the correct DIScope metadata instance.
3436
//
@@ -68,11 +70,29 @@ pub fn create_scope_map(cx: &CrateContext,
6870
return scope_map;
6971
}
7072

73+
#[derive(Clone, Copy, Debug)]
74+
pub struct MirDebugScope {
75+
pub scope_metadata: DIScope,
76+
pub start_pos: BytePos,
77+
pub end_pos: BytePos,
78+
}
79+
80+
impl MirDebugScope {
81+
pub fn is_valid(&self) -> bool {
82+
!self.scope_metadata.is_null()
83+
}
84+
}
85+
7186
/// Produce DIScope DIEs for each MIR Scope which has variables defined in it.
7287
/// If debuginfo is disabled, the returned vector is empty.
73-
pub fn create_mir_scopes(fcx: &FunctionContext) -> IndexVec<VisibilityScope, DIScope> {
88+
pub fn create_mir_scopes(fcx: &FunctionContext) -> IndexVec<VisibilityScope, MirDebugScope> {
7489
let mir = fcx.mir.clone().expect("create_mir_scopes: missing MIR for fn");
75-
let mut scopes = IndexVec::from_elem(ptr::null_mut(), &mir.visibility_scopes);
90+
let null_scope = MirDebugScope {
91+
scope_metadata: ptr::null_mut(),
92+
start_pos: BytePos(0),
93+
end_pos: BytePos(0)
94+
};
95+
let mut scopes = IndexVec::from_elem(null_scope, &mir.visibility_scopes);
7696

7797
let fn_metadata = match fcx.debug_context {
7898
FunctionDebugContext::RegularContext(box ref data) => data.fn_metadata,
@@ -102,8 +122,8 @@ fn make_mir_scope(ccx: &CrateContext,
102122
has_variables: &BitVector,
103123
fn_metadata: DISubprogram,
104124
scope: VisibilityScope,
105-
scopes: &mut IndexVec<VisibilityScope, DIScope>) {
106-
if !scopes[scope].is_null() {
125+
scopes: &mut IndexVec<VisibilityScope, MirDebugScope>) {
126+
if scopes[scope].is_valid() {
107127
return;
108128
}
109129

@@ -113,7 +133,12 @@ fn make_mir_scope(ccx: &CrateContext,
113133
scopes[parent]
114134
} else {
115135
// The root is the function itself.
116-
scopes[scope] = fn_metadata;
136+
let loc = span_start(ccx, mir.span);
137+
scopes[scope] = MirDebugScope {
138+
scope_metadata: fn_metadata,
139+
start_pos: loc.file.start_pos,
140+
end_pos: loc.file.end_pos,
141+
};
117142
return;
118143
};
119144

@@ -124,22 +149,27 @@ fn make_mir_scope(ccx: &CrateContext,
124149
// However, we don't skip creating a nested scope if
125150
// our parent is the root, because we might want to
126151
// put arguments in the root and not have shadowing.
127-
if parent_scope != fn_metadata {
152+
if parent_scope.scope_metadata != fn_metadata {
128153
scopes[scope] = parent_scope;
129154
return;
130155
}
131156
}
132157

133158
let loc = span_start(ccx, scope_data.span);
134-
scopes[scope] = unsafe {
135159
let file_metadata = file_metadata(ccx, &loc.file.name, &loc.file.abs_path);
160+
let scope_metadata = unsafe {
136161
llvm::LLVMRustDIBuilderCreateLexicalBlock(
137162
DIB(ccx),
138-
parent_scope,
163+
parent_scope.scope_metadata,
139164
file_metadata,
140165
loc.line as c_uint,
141166
loc.col.to_usize() as c_uint)
142167
};
168+
scopes[scope] = MirDebugScope {
169+
scope_metadata: scope_metadata,
170+
start_pos: loc.file.start_pos,
171+
end_pos: loc.file.end_pos,
172+
};
143173
}
144174

145175
// local helper functions for walking the AST.

src/librustc_trans/debuginfo/metadata.rs

+15-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use context::SharedCrateContext;
2323
use session::Session;
2424

2525
use llvm::{self, ValueRef};
26-
use llvm::debuginfo::{DIType, DIFile, DIScope, DIDescriptor, DICompositeType};
26+
use llvm::debuginfo::{DIType, DIFile, DIScope, DIDescriptor, DICompositeType, DILexicalBlock};
2727

2828
use rustc::hir::def_id::DefId;
2929
use rustc::hir::pat_util;
@@ -2104,3 +2104,17 @@ pub fn create_argument_metadata(bcx: Block, arg: &hir::Arg) {
21042104
span);
21052105
})
21062106
}
2107+
2108+
// Creates an "extension" of an existing DIScope into another file.
2109+
pub fn extend_scope_to_file(ccx: &CrateContext,
2110+
scope_metadata: DIScope,
2111+
file: &syntax_pos::FileMap)
2112+
-> DILexicalBlock {
2113+
let file_metadata = file_metadata(ccx, &file.name, &file.abs_path);
2114+
unsafe {
2115+
llvm::LLVMRustDIBuilderCreateLexicalBlockFile(
2116+
DIB(ccx),
2117+
scope_metadata,
2118+
file_metadata)
2119+
}
2120+
}

src/librustc_trans/debuginfo/mod.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ use std::cell::{Cell, RefCell};
4343
use std::ffi::CString;
4444
use std::ptr;
4545

46-
use syntax_pos::{self, Span, Pos};
46+
use syntax_pos::{self, Span};
4747
use syntax::ast;
4848
use syntax::attr::IntType;
4949

@@ -55,7 +55,7 @@ pub mod metadata;
5555
mod create_scope_map;
5656
mod source_loc;
5757

58-
pub use self::create_scope_map::create_mir_scopes;
58+
pub use self::create_scope_map::{create_mir_scopes, MirDebugScope};
5959
pub use self::source_loc::start_emitting_source_locations;
6060
pub use self::source_loc::get_cleanup_debug_loc_for_ast_node;
6161
pub use self::source_loc::with_source_location_override;
@@ -64,6 +64,7 @@ pub use self::metadata::create_argument_metadata;
6464
pub use self::metadata::create_captured_var_metadata;
6565
pub use self::metadata::create_global_var_metadata;
6666
pub use self::metadata::create_local_var_metadata;
67+
pub use self::metadata::extend_scope_to_file;
6768

6869
#[allow(non_upper_case_globals)]
6970
const DW_TAG_auto_variable: c_uint = 0x100;
@@ -509,7 +510,7 @@ pub fn declare_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
509510
argument_index)
510511
};
511512
source_loc::set_debug_location(cx, None,
512-
InternalDebugLocation::new(scope_metadata, loc.line, loc.col.to_usize()));
513+
InternalDebugLocation::KnownLocation(scope_metadata, span.lo, None));
513514
unsafe {
514515
let debug_loc = llvm::LLVMGetCurrentDebugLocation(cx.raw_builder());
515516
let instr = llvm::LLVMRustDIBuilderInsertDeclareAtEnd(
@@ -542,7 +543,7 @@ pub fn declare_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
542543
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
543544
pub enum DebugLoc {
544545
At(ast::NodeId, Span),
545-
ScopeAt(DIScope, Span),
546+
ScopeAt(DIScope, Span, Option<(DIScope, Span)>),
546547
None
547548
}
548549

src/librustc_trans/debuginfo/source_loc.rs

+40-34
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
use self::InternalDebugLocation::*;
1212

13-
use super::utils::{debug_context, span_start};
13+
use super::utils::debug_context;
1414
use super::metadata::{scope_metadata,UNKNOWN_COLUMN_NUMBER};
1515
use super::{FunctionDebugContext, DebugLoc};
1616

@@ -21,7 +21,7 @@ use common::{NodeIdAndSpan, CrateContext, FunctionContext};
2121

2222
use libc::c_uint;
2323
use std::ptr;
24-
use syntax_pos::{self, Span, Pos};
24+
use syntax_pos::{self, Span, BytePos};
2525
use syntax::ast;
2626

2727
pub fn get_cleanup_debug_loc_for_ast_node<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
@@ -108,21 +108,20 @@ pub fn set_source_location(fcx: &FunctionContext,
108108
}
109109

110110
let dbg_loc = if function_debug_context.source_locations_enabled.get() {
111-
let (scope, span) = match debug_loc {
111+
match debug_loc {
112112
DebugLoc::At(node_id, span) => {
113-
(scope_metadata(fcx, node_id, span), span)
113+
let scope = scope_metadata(fcx, node_id, span);
114+
KnownLocation(scope, span.lo, None)
114115
}
115-
DebugLoc::ScopeAt(scope, span) => (scope, span),
116-
DebugLoc::None => {
117-
set_debug_location(fcx.ccx, builder, UnknownLocation);
118-
return;
116+
DebugLoc::ScopeAt(scope, span, inlined_at) => {
117+
let inlined_at_loc = match inlined_at {
118+
Some((scope, span)) => Some((scope, span.lo)),
119+
None => None
120+
};
121+
KnownLocation(scope, span.lo, inlined_at_loc)
119122
}
120-
};
121-
122-
debug!("set_source_location: {}",
123-
fcx.ccx.sess().codemap().span_to_string(span));
124-
let loc = span_start(fcx.ccx, span);
125-
InternalDebugLocation::new(scope, loc.line, loc.col.to_usize())
123+
DebugLoc::None => UnknownLocation
124+
}
126125
} else {
127126
UnknownLocation
128127
};
@@ -173,23 +172,12 @@ pub fn start_emitting_source_locations(fcx: &FunctionContext) {
173172
}
174173
}
175174

176-
177175
#[derive(Copy, Clone, PartialEq)]
178176
pub enum InternalDebugLocation {
179-
KnownLocation { scope: DIScope, line: usize, col: usize },
177+
KnownLocation(DIScope, BytePos, Option<(DIScope, BytePos)>),
180178
UnknownLocation
181179
}
182180

183-
impl InternalDebugLocation {
184-
pub fn new(scope: DIScope, line: usize, col: usize) -> InternalDebugLocation {
185-
KnownLocation {
186-
scope: scope,
187-
line: line,
188-
col: col,
189-
}
190-
}
191-
}
192-
193181
pub fn set_debug_location(cx: &CrateContext,
194182
builder: Option<llvm::BuilderRef>,
195183
debug_location: InternalDebugLocation) {
@@ -199,19 +187,37 @@ pub fn set_debug_location(cx: &CrateContext,
199187
}
200188
}
201189

190+
let cm = cx.sess().codemap();
202191
let metadata_node = match debug_location {
203-
KnownLocation { scope, line, .. } => {
204-
// Always set the column to zero like Clang and GCC
205-
let col = UNKNOWN_COLUMN_NUMBER;
206-
debug!("setting debug location to {} {}", line, col);
207-
192+
KnownLocation(scope, pos, inlined_at) => {
193+
194+
let inlined_at_loc = match inlined_at {
195+
Some((scope, pos)) => {
196+
let loc = cm.lookup_char_pos(pos);
197+
unsafe {
198+
llvm::LLVMRustValueAsMetadata(
199+
llvm::LLVMRustDIBuilderCreateDebugLocation(
200+
debug_context(cx).llcontext,
201+
loc.line as c_uint,
202+
UNKNOWN_COLUMN_NUMBER as c_uint,
203+
scope,
204+
ptr::null_mut())
205+
)
206+
}
207+
},
208+
None => ptr::null_mut()
209+
};
210+
211+
let loc = cm.lookup_char_pos(pos);
212+
debug!("setting debug location to line {}", loc.line);
213+
// Set the column to zero like Clang and GCC
208214
unsafe {
209215
llvm::LLVMRustDIBuilderCreateDebugLocation(
210216
debug_context(cx).llcontext,
211-
line as c_uint,
212-
col as c_uint,
217+
loc.line as c_uint,
218+
UNKNOWN_COLUMN_NUMBER as c_uint,
213219
scope,
214-
ptr::null_mut())
220+
inlined_at_loc)
215221
}
216222
}
217223
UnknownLocation => {

src/librustc_trans/intrinsic.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
121121
let name = tcx.item_name(def_id).as_str();
122122

123123
let span = match call_debug_location {
124-
DebugLoc::At(_, span) | DebugLoc::ScopeAt(_, span) => span,
124+
DebugLoc::At(_, span) | DebugLoc::ScopeAt(_, span, _) => span,
125125
DebugLoc::None => {
126126
span_bug!(fcx.span.unwrap_or(DUMMY_SP),
127127
"intrinsic `{}` called with missing span", name);

0 commit comments

Comments
 (0)