Skip to content

Commit f2dbeba

Browse files
committed
Improved support of collapse_debuginfo attribute for macros.
1 parent ca9ff83 commit f2dbeba

File tree

8 files changed

+513
-39
lines changed

8 files changed

+513
-39
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);
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)
246241
}
247242

248243
fn spill_operand_to_stack(

compiler/rustc_middle/src/ty/mod.rs

+11-11
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::{hygiene, ExpnId, ExpnKind, Span};
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,21 @@ 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.
2518+
/// Returns corrected span if the debuginfo for `span` should be collapsed to the outermost
2519+
/// expansion site (with collapse_debuginfo attribute if the corresponding feature enabled).
2520+
/// Only applies when `Span` is the result of macro expansion.
25202521
///
25212522
/// - 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+
/// and only when a (some enclosing) macro definition is annotated with `#[collapse_debuginfo]`.
25232524
/// - If `collapse_debuginfo` is not enabled, then debuginfo is collapsed by default.
25242525
///
25252526
/// 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-
}
2527+
pub fn collapsed_debuginfo(self, span: Span, upto: Span) -> Span {
2528+
if self.sess.opts.unstable_opts.debug_macros || !span.from_expansion() {
2529+
return span;
2530+
}
2531+
let collapse_debuginfo_enabled = self.features().collapse_debuginfo;
2532+
hygiene::walk_chain_collapsed(span, upto, collapse_debuginfo_enabled)
25332533
}
25342534

25352535
#[inline]

compiler/rustc_span/src/hygiene.rs

+33-1
Original file line numberDiff line numberDiff line change
@@ -443,18 +443,46 @@ 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: Span,
465+
collapse_debuginfo_enabled: bool,
466+
) -> Span {
467+
let orig_span = span;
468+
let mut ret_span = span;
469+
470+
debug!("walk_chain_collapsed({:?}, {:?})", span, to);
471+
debug!("walk_chain_collapsed: span ctxt = {:?}", span.ctxt());
472+
while !span.eq_ctxt(to) && span.from_expansion() {
473+
let outer_expn = self.outer_expn(span.ctxt());
474+
debug!("walk_chain_collapsed({:?}): outer_expn={:?}", span, outer_expn);
475+
let expn_data = self.expn_data(outer_expn);
476+
debug!("walk_chain_collapsed({:?}): expn_data={:?}", span, expn_data);
477+
span = expn_data.call_site;
478+
if !collapse_debuginfo_enabled || expn_data.collapse_debuginfo {
479+
ret_span = span;
480+
}
481+
}
482+
debug!("walk_chain_collapsed: for span {:?} >>> return span = {:?}", orig_span, ret_span);
483+
ret_span
484+
}
485+
458486
fn adjust(&self, ctxt: &mut SyntaxContext, expn_id: ExpnId) -> Option<ExpnId> {
459487
let mut scope = None;
460488
while !self.is_descendant_of(expn_id, self.outer_expn(*ctxt)) {
@@ -571,6 +599,10 @@ pub fn walk_chain(span: Span, to: SyntaxContext) -> Span {
571599
HygieneData::with(|data| data.walk_chain(span, to))
572600
}
573601

602+
pub fn walk_chain_collapsed(span: Span, to: Span, collapse_debuginfo_enabled: bool) -> Span {
603+
HygieneData::with(|hdata| hdata.walk_chain_collapsed(span, to, collapse_debuginfo_enabled))
604+
}
605+
574606
pub fn update_dollar_crate_names(mut get_name: impl FnMut(SyntaxContext) -> Symbol) {
575607
// The new contexts that need updating are at the end of the list and have `$crate` as a name.
576608
let (len, to_update) = HygieneData::with(|data| {

compiler/rustc_span/src/lib.rs

-7
Original file line numberDiff line numberDiff line change
@@ -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,124 @@
1+
// ignore-lldb
2+
#![feature(collapse_debuginfo)]
3+
4+
// Test that statement, skipped/added/reordered by macros, is correctly processed in debuginfo.
5+
// When nested macros instantiations are tagged with collapse_debuginfo attribute,
6+
// debug info should be corrected to the first outer macro instantiation
7+
// without collapse_debuginfo attribute.
8+
// collapse_debuginfo feature enabled.
9+
10+
// compile-flags:-g
11+
12+
// === GDB TESTS ===================================================================================
13+
14+
// gdb-command:run
15+
// gdb-command:next
16+
// gdb-command:frame
17+
// gdb-check:[...]#loc_rem_call1[...]
18+
// gdb-command:step
19+
// gdb-command:frame
20+
// gdb-check:[...]#loc_call1_pre[...]
21+
// gdb-command:next
22+
// gdb-command:frame
23+
// gdb-check:[...]#loc_in_proxy[...]
24+
// gdb-command:next 2
25+
// gdb-check:[...]#loc_rem_call3[...]
26+
// gdb-command:next
27+
// gdb-command:frame
28+
// gdb-check:[...]#loc_add_call1[...]
29+
// gdb-command:step
30+
// gdb-command:frame
31+
// gdb-check:[...]#loc_call1_pre[...]
32+
// gdb-command:next
33+
// gdb-command:frame
34+
// gdb-check:[...]#loc_in_proxy[...]
35+
// gdb-command:next 2
36+
// gdb-check:[...]#loc_add_macro[...]
37+
// gdb-command:next
38+
// gdb-command:frame
39+
// gdb-check:[...]#loc_add_call3[...]
40+
// gdb-command:next
41+
// gdb-command:frame
42+
// gdb-check:[...]#loc_reorder_call2[...]
43+
// gdb-command:next
44+
// gdb-command:frame
45+
// gdb-check:[...]#loc_reorder_call3[...]
46+
// gdb-command:next
47+
// gdb-command:frame
48+
// gdb-check:[...]#loc_reorder_call1[...]
49+
// gdb-command:step
50+
// gdb-command:frame
51+
// gdb-check:[...]#loc_call1_pre[...]
52+
// gdb-command:next
53+
// gdb-command:frame
54+
// gdb-check:[...]#loc_in_proxy[...]
55+
// gdb-command:next 2
56+
// gdb-command:frame
57+
// gdb-command:continue
58+
59+
#[inline(never)]
60+
fn myprintln_impl(text: &str) {
61+
println!("{}", text)
62+
}
63+
64+
#[collapse_debuginfo]
65+
macro_rules! myprintln {
66+
($($arg:tt)*) => {{
67+
myprintln_impl($($arg)*);
68+
}};
69+
}
70+
71+
macro_rules! proxy_println {
72+
($($arg:tt)*) => {{
73+
myprintln!($($arg)*); // #loc_in_proxy
74+
}};
75+
}
76+
77+
// Macro accepts 3 statements and removes the 2nd statement
78+
macro_rules! remove_second_statement {
79+
($s1:stmt; $s2:stmt; $s3:stmt;) => { $s1 $s3 }
80+
}
81+
82+
macro_rules! add_second_statement {
83+
($s1:stmt; $s3:stmt;) => {
84+
$s1
85+
call2(); // #loc_add_macro
86+
$s3
87+
}
88+
}
89+
90+
macro_rules! reorder_statements {
91+
($s1:stmt; $s2:stmt; $s3:stmt;) => { $s2 $s3 $s1 }
92+
}
93+
94+
fn call1() {
95+
let rv = 0; // #loc_call1_pre
96+
proxy_println!("one"); // #loc_call1
97+
}
98+
99+
fn call2() {
100+
proxy_println!("two"); // #loc_call2
101+
}
102+
103+
fn call3() {
104+
proxy_println!("three"); // #loc_call3
105+
}
106+
107+
fn main() {
108+
let ret = 0; // #break, step should go to call1
109+
remove_second_statement! { // #loc_rem_hdr
110+
call1(); // #loc_rem_call1
111+
call2(); // #loc_rem_call2
112+
call3(); // #loc_rem_call3
113+
}
114+
add_second_statement! { // #loc_add_hdr
115+
call1(); // #loc_add_call1
116+
call3(); // #loc_add_call3
117+
}
118+
reorder_statements! { // #loc_reorder_hdr
119+
call1(); // #loc_reorder_call1
120+
call2(); // #loc_reorder_call2
121+
call3(); // #loc_reorder_call3
122+
}
123+
std::process::exit(ret); // #loc_exit
124+
}

0 commit comments

Comments
 (0)