Skip to content

Commit dc993ca

Browse files
committed
Improved support of collapse_debuginfo attribute for macros.
1 parent 77d1699 commit dc993ca

File tree

8 files changed

+504
-47
lines changed

8 files changed

+504
-47
lines changed

compiler/rustc_codegen_cranelift/src/debuginfo/line_info.rs

+1-9
Original file line numberDiff line numberDiff line change
@@ -68,15 +68,7 @@ impl DebugContext {
6868
// In order to have a good line stepping behavior in debugger, we overwrite debug
6969
// locations of macro expansions with that of the outermost expansion site (when the macro is
7070
// annotated with `#[collapse_debuginfo]` or when `-Zdebug-macros` is provided).
71-
let span = if tcx.should_collapse_debuginfo(span) {
72-
span
73-
} else {
74-
// Walk up the macro expansion chain until we reach a non-expanded span.
75-
// We also stop at the function body level because no line stepping can occur
76-
// at the level above that.
77-
rustc_span::hygiene::walk_chain(span, function_span.ctxt())
78-
};
79-
71+
let span = tcx.collapsed_debuginfo(span, function_span.ctxt());
8072
match tcx.sess.source_map().lookup_line(span.lo()) {
8173
Ok(SourceFileAndLine { sf: file, line }) => {
8274
let line_pos = file.lines()[line];

compiler/rustc_codegen_ssa/src/mir/debuginfo.rs

+6-11
Original file line numberDiff line numberDiff line change
@@ -228,21 +228,16 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
228228
/// In order to have a good line stepping behavior in debugger, we overwrite debug
229229
/// locations of macro expansions with that of the outermost expansion site (when the macro is
230230
/// annotated with `#[collapse_debuginfo]` or when `-Zdebug-macros` is provided).
231-
fn adjust_span_for_debugging(&self, mut span: Span) -> Span {
231+
fn adjust_span_for_debugging(&self, span: Span) -> Span {
232232
// Bail out if debug info emission is not enabled.
233233
if self.debug_context.is_none() {
234234
return span;
235235
}
236-
237-
if self.cx.tcx().should_collapse_debuginfo(span) {
238-
// Walk up the macro expansion chain until we reach a non-expanded span.
239-
// We also stop at the function body level because no line stepping can occur
240-
// at the level above that.
241-
// Use span of the outermost expansion site, while keeping the original lexical scope.
242-
span = rustc_span::hygiene::walk_chain(span, self.mir.span.ctxt());
243-
}
244-
245-
span
236+
// Walk up the macro expansion chain until we reach a non-expanded span.
237+
// We also stop at the function body level because no line stepping can occur
238+
// at the level above that.
239+
// Use span of the outermost expansion site, while keeping the original lexical scope.
240+
self.cx.tcx().collapsed_debuginfo(span, self.mir.span.ctxt())
246241
}
247242

248243
fn spill_operand_to_stack(

compiler/rustc_middle/src/ty/mod.rs

+5-16
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ use rustc_session::lint::LintBuffer;
5050
pub use rustc_session::lint::RegisteredTools;
5151
use rustc_span::hygiene::MacroKind;
5252
use rustc_span::symbol::{kw, sym, Ident, Symbol};
53-
use rustc_span::{ExpnId, ExpnKind, Span};
53+
use rustc_span::{ExpnId, ExpnKind, Span, SyntaxContext};
5454
use rustc_target::abi::{Align, FieldIdx, Integer, IntegerType, VariantIdx};
5555
pub use rustc_target::abi::{ReprFlags, ReprOptions};
5656
pub use rustc_type_ir::{DebugWithInfcx, InferCtxtLike, WithInfcx};
@@ -2515,21 +2515,10 @@ impl<'tcx> TyCtxt<'tcx> {
25152515
(ident, scope)
25162516
}
25172517

2518-
/// Returns `true` if the debuginfo for `span` should be collapsed to the outermost expansion
2519-
/// site. Only applies when `Span` is the result of macro expansion.
2520-
///
2521-
/// - If the `collapse_debuginfo` feature is enabled then debuginfo is not collapsed by default
2522-
/// and only when a macro definition is annotated with `#[collapse_debuginfo]`.
2523-
/// - If `collapse_debuginfo` is not enabled, then debuginfo is collapsed by default.
2524-
///
2525-
/// When `-Zdebug-macros` is provided then debuginfo will never be collapsed.
2526-
pub fn should_collapse_debuginfo(self, span: Span) -> bool {
2527-
!self.sess.opts.unstable_opts.debug_macros
2528-
&& if self.features().collapse_debuginfo {
2529-
span.in_macro_expansion_with_collapse_debuginfo()
2530-
} else {
2531-
span.from_expansion()
2532-
}
2518+
pub fn collapsed_debuginfo(self, span: Span, upto: SyntaxContext) -> Span {
2519+
let collapse_enabled = !self.sess.opts.unstable_opts.debug_macros;
2520+
let attr_enabled = self.features().collapse_debuginfo;
2521+
rustc_span::hygiene::walk_chain_collapsed(span, upto, collapse_enabled, attr_enabled)
25332522
}
25342523

25352524
#[inline]

compiler/rustc_span/src/hygiene.rs

+52-3
Original file line numberDiff line numberDiff line change
@@ -377,7 +377,7 @@ impl HygieneData {
377377
self.local_expn_data[expn_id].as_ref().expect("no expansion data for an expansion ID")
378378
}
379379

380-
fn expn_data(&self, expn_id: ExpnId) -> &ExpnData {
380+
pub fn expn_data(&self, expn_id: ExpnId) -> &ExpnData {
381381
if let Some(expn_id) = expn_id.as_local() {
382382
self.local_expn_data[expn_id].as_ref().expect("no expansion data for an expansion ID")
383383
} else {
@@ -412,7 +412,7 @@ impl HygieneData {
412412
self.syntax_context_data[ctxt.0 as usize].opaque_and_semitransparent
413413
}
414414

415-
fn outer_expn(&self, ctxt: SyntaxContext) -> ExpnId {
415+
pub fn outer_expn(&self, ctxt: SyntaxContext) -> ExpnId {
416416
self.syntax_context_data[ctxt.0 as usize].outer_expn
417417
}
418418

@@ -443,18 +443,52 @@ impl HygieneData {
443443
}
444444

445445
fn walk_chain(&self, mut span: Span, to: SyntaxContext) -> Span {
446+
let orig_span = span;
446447
debug!("walk_chain({:?}, {:?})", span, to);
447448
debug!("walk_chain: span ctxt = {:?}", span.ctxt());
448-
while span.from_expansion() && span.ctxt() != to {
449+
while span.ctxt() != to && span.from_expansion() {
449450
let outer_expn = self.outer_expn(span.ctxt());
450451
debug!("walk_chain({:?}): outer_expn={:?}", span, outer_expn);
451452
let expn_data = self.expn_data(outer_expn);
452453
debug!("walk_chain({:?}): expn_data={:?}", span, expn_data);
453454
span = expn_data.call_site;
454455
}
456+
debug!("walk_chain: for span {:?} >>> return span = {:?}", orig_span, span);
455457
span
456458
}
457459

460+
// We need to walk up and update return span if we meet macro instantiation to be collapsed
461+
fn walk_chain_collapsed(
462+
&self,
463+
mut span: Span,
464+
to: SyntaxContext,
465+
collapse_enabled: bool,
466+
attr_enabled: bool,
467+
) -> Span {
468+
if !collapse_enabled {
469+
return span;
470+
}
471+
let orig_span = span;
472+
let mut rv_span = span;
473+
474+
debug!("walk_chain_collapsed({:?}, {:?})", span, to);
475+
debug!("walk_chain_collapsed: span ctxt = {:?}", span.ctxt());
476+
while span.ctxt() != to && span.from_expansion() {
477+
let outer_expn = self.outer_expn(span.ctxt());
478+
debug!("walk_chain_collapsed({:?}): outer_expn={:?}", span, outer_expn);
479+
let expn_data = self.expn_data(outer_expn);
480+
debug!("walk_chain_collapsed({:?}): expn_data={:?}", span, expn_data);
481+
span = expn_data.call_site;
482+
if !attr_enabled ||
483+
matches!(expn_data.kind, ExpnKind::Macro(..)) && expn_data.collapse_debuginfo
484+
{
485+
rv_span = span;
486+
}
487+
}
488+
debug!("walk_chain_collapsed: for span {:?} >>> return span = {:?}", orig_span, rv_span);
489+
rv_span
490+
}
491+
458492
fn adjust(&self, ctxt: &mut SyntaxContext, expn_id: ExpnId) -> Option<ExpnId> {
459493
let mut scope = None;
460494
while !self.is_descendant_of(expn_id, self.outer_expn(*ctxt)) {
@@ -571,6 +605,21 @@ pub fn walk_chain(span: Span, to: SyntaxContext) -> Span {
571605
HygieneData::with(|data| data.walk_chain(span, to))
572606
}
573607

608+
pub fn walk_chain_collapsed(
609+
span: Span,
610+
to: SyntaxContext,
611+
collapse_enabled: bool,
612+
attr_enabled: bool,
613+
) -> Span {
614+
HygieneData::with(|hdata| {
615+
if collapse_enabled && span.from_expansion() {
616+
hdata.walk_chain_collapsed(span, to, collapse_enabled, attr_enabled)
617+
} else {
618+
span
619+
}
620+
})
621+
}
622+
574623
pub fn update_dollar_crate_names(mut get_name: impl FnMut(SyntaxContext) -> Symbol) {
575624
// The new contexts that need updating are at the end of the list and have `$crate` as a name.
576625
let (len, to_update) = HygieneData::with(|data| {

compiler/rustc_span/src/lib.rs

+1-8
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,9 @@ use source_map::SourceMap;
5353
pub mod edition;
5454
use edition::Edition;
5555
pub mod hygiene;
56-
use hygiene::Transparency;
5756
pub use hygiene::{DesugaringKind, ExpnKind, MacroKind};
5857
pub use hygiene::{ExpnData, ExpnHash, ExpnId, LocalExpnId, SyntaxContext};
58+
use hygiene::{Transparency};
5959
use rustc_data_structures::stable_hasher::HashingControls;
6060
pub mod def_id;
6161
use def_id::{CrateNum, DefId, DefPathHash, LocalDefId, LOCAL_CRATE};
@@ -568,13 +568,6 @@ impl Span {
568568
self.ctxt() != SyntaxContext::root()
569569
}
570570

571-
/// Returns `true` if `span` originates in a macro's expansion where debuginfo should be
572-
/// collapsed.
573-
pub fn in_macro_expansion_with_collapse_debuginfo(self) -> bool {
574-
let outer_expn = self.ctxt().outer_expn_data();
575-
matches!(outer_expn.kind, ExpnKind::Macro(..)) && outer_expn.collapse_debuginfo
576-
}
577-
578571
/// Returns `true` if `span` originates in a derive-macro's expansion.
579572
pub fn in_derive_expansion(self) -> bool {
580573
matches!(self.ctxt().outer_expn_data().kind, ExpnKind::Macro(MacroKind::Derive, _))
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
// ignore-lldb
2+
#![feature(collapse_debuginfo)]
3+
4+
// Test that statement, skipped by macros, is correctly processed in debuginfo
5+
6+
// compile-flags:-g
7+
8+
// === GDB TESTS ===================================================================================
9+
10+
// gdb-command:run
11+
// gdb-command:next
12+
// gdb-check:[...]#loc_rem_call1[...]
13+
// gdb-command:step
14+
// gdb-command:frame
15+
// gdb-check:[...]#loc_call1_pre[...]
16+
// gdb-command:next
17+
// gdb-command:frame
18+
// gdb-check:[...]#loc_in_proxy[...]
19+
// gdb-command:finish
20+
// gdb-check:[...]#loc_rem_call3[...]
21+
// gdb-command:next
22+
// gdb-command:frame
23+
// gdb-check:[...]#loc_add_call1[...]
24+
// gdb-command:step
25+
// gdb-command:frame
26+
// gdb-check:[...]#loc_call1_pre[...]
27+
// gdb-command:next
28+
// gdb-command:frame
29+
// gdb-check:[...]#loc_in_proxy[...]
30+
// gdb-command:finish
31+
// gdb-check:[...]#loc_add_macro[...]
32+
// gdb-command:next
33+
// gdb-command:frame
34+
// gdb-check:[...]#loc_add_call3[...]
35+
// gdb-command:next
36+
// gdb-command:frame
37+
// gdb-check:[...]#loc_reorder_call2[...]
38+
// gdb-command:next
39+
// gdb-command:frame
40+
// gdb-check:[...]#loc_reorder_call3[...]
41+
// gdb-command:next
42+
// gdb-command:frame
43+
// gdb-check:[...]#loc_reorder_call1[...]
44+
// gdb-command:step
45+
// gdb-command:frame
46+
// gdb-check:[...]#loc_call1_pre[...]
47+
// gdb-command:next
48+
// gdb-command:frame
49+
// gdb-check:[...]#loc_in_proxy[...]
50+
// gdb-command:finish
51+
// gdb-check:[...]#loc_exit[...]
52+
// gdb-command:continue
53+
54+
#[collapse_debuginfo]
55+
macro_rules! myprintln {
56+
($($arg:tt)*) => {{
57+
println!($($arg)*);
58+
}};
59+
}
60+
61+
macro_rules! proxy_println {
62+
($($arg:tt)*) => {{
63+
myprintln!($($arg)*); // #loc_in_proxy
64+
}};
65+
}
66+
67+
// Macro accepts 3 statements and removes the 2nd statement
68+
macro_rules! remove_second_statement {
69+
($s1:stmt; $s2:stmt; $s3:stmt;) => { $s1 $s3 }
70+
}
71+
72+
macro_rules! add_second_statement {
73+
($s1:stmt; $s3:stmt;) => { $s1 call2(); $s3 } // #loc_add_macro
74+
}
75+
76+
macro_rules! reorder_statements {
77+
($s1:stmt; $s2:stmt; $s3:stmt;) => { $s2 $s3 $s1 }
78+
}
79+
80+
fn call1() {
81+
let rv = 0; // #loc_call1_pre
82+
proxy_println!("one"); // #loc_call1
83+
}
84+
85+
fn call2() {
86+
proxy_println!("two"); // #loc_call2
87+
}
88+
89+
fn call3() {
90+
proxy_println!("three"); // #loc_call3
91+
}
92+
93+
fn main() {
94+
let ret = 0; // #break, step should go to call1
95+
remove_second_statement! { // #loc_rem_hdr
96+
call1(); // #loc_rem_call1
97+
call2(); // #loc_rem_call2
98+
call3(); // #loc_rem_call3
99+
}
100+
add_second_statement! { // #loc_add_hdr
101+
call1(); // #loc_add_call1
102+
call3(); // #loc_add_call3
103+
}
104+
reorder_statements! { // #loc_reorder_hdr
105+
call1(); // #loc_reorder_call1
106+
call2(); // #loc_reorder_call2
107+
call3(); // #loc_reorder_call3
108+
}
109+
std::process::exit(ret); // #loc_exit
110+
}

0 commit comments

Comments
 (0)