Skip to content

Commit 6421427

Browse files
committed
Move Span lowering from debuginfo finalization to codegen
This removes the dependency on TyCtxt from the debuginfo finalization code.
1 parent 0534a55 commit 6421427

File tree

4 files changed

+100
-114
lines changed

4 files changed

+100
-114
lines changed

src/base.rs

Lines changed: 3 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@ use rustc_middle::ty::layout::FnAbiOf;
77
use rustc_middle::ty::print::with_no_trimmed_paths;
88
use rustc_middle::ty::SymbolName;
99

10-
use indexmap::IndexSet;
11-
1210
use crate::constant::ConstantCx;
1311
use crate::debuginfo::FunctionDebugContext;
1412
use crate::prelude::*;
@@ -20,8 +18,6 @@ struct CodegenedFunction<'tcx> {
2018
func: Function,
2119
clif_comments: CommentWriter,
2220
func_debug_cx: Option<FunctionDebugContext>,
23-
function_span: Span,
24-
source_info_set: IndexSet<SourceInfo>,
2521
}
2622

2723
pub(crate) fn codegen_and_compile_fn<'tcx>(
@@ -37,7 +33,7 @@ pub(crate) fn codegen_and_compile_fn<'tcx>(
3733
let cached_func = std::mem::replace(&mut cached_context.func, Function::new());
3834
let codegened_func = codegen_fn(tcx, cx, cached_func, module, instance);
3935

40-
compile_fn(tcx, cx, cached_context, module, codegened_func);
36+
compile_fn(cx, cached_context, module, codegened_func);
4137
}
4238

4339
fn codegen_fn<'tcx>(
@@ -110,7 +106,7 @@ fn codegen_fn<'tcx>(
110106
caller_location: None, // set by `codegen_fn_prelude`
111107

112108
clif_comments,
113-
source_info_set: indexmap::IndexSet::new(),
109+
last_source_file: None,
114110
next_ssa_var: 0,
115111
};
116112

@@ -119,8 +115,6 @@ fn codegen_fn<'tcx>(
119115
// Recover all necessary data from fx, before accessing func will prevent future access to it.
120116
let clif_comments = fx.clif_comments;
121117
let func_debug_cx = fx.func_debug_cx;
122-
let function_span = fx.mir.span;
123-
let source_info_set = fx.source_info_set;
124118

125119
fx.constants_cx.finalize(fx.tcx, &mut *fx.module);
126120

@@ -138,19 +132,10 @@ fn codegen_fn<'tcx>(
138132
// Verify function
139133
verify_func(tcx, &clif_comments, &func);
140134

141-
CodegenedFunction {
142-
symbol_name,
143-
func_id,
144-
func,
145-
clif_comments,
146-
func_debug_cx,
147-
function_span,
148-
source_info_set,
149-
}
135+
CodegenedFunction { symbol_name, func_id, func, clif_comments, func_debug_cx }
150136
}
151137

152138
fn compile_fn<'tcx>(
153-
tcx: TyCtxt<'tcx>,
154139
cx: &mut crate::CodegenCx,
155140
cached_context: &mut Context,
156141
module: &mut dyn Module,
@@ -234,11 +219,8 @@ fn compile_fn<'tcx>(
234219
if let Some(debug_context) = debug_context {
235220
codegened_func.func_debug_cx.unwrap().finalize(
236221
debug_context,
237-
tcx,
238222
codegened_func.func_id,
239223
context,
240-
codegened_func.function_span,
241-
&codegened_func.source_info_set,
242224
);
243225
}
244226
unwind_context.add_function(codegened_func.func_id, &context, isa);

src/common.rs

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
use cranelift_codegen::isa::TargetFrontendConfig;
2+
use gimli::write::FileId;
3+
4+
use rustc_data_structures::sync::Lrc;
25
use rustc_index::vec::IndexVec;
36
use rustc_middle::ty::layout::{
47
FnAbiError, FnAbiOfHelpers, FnAbiRequest, LayoutError, LayoutOfHelpers,
58
};
69
use rustc_middle::ty::SymbolName;
10+
use rustc_span::SourceFile;
711
use rustc_target::abi::call::FnAbi;
812
use rustc_target::abi::{Integer, Primitive};
913
use rustc_target::spec::{HasTargetSpec, Target};
@@ -254,7 +258,11 @@ pub(crate) struct FunctionCx<'m, 'clif, 'tcx: 'm> {
254258
pub(crate) caller_location: Option<CValue<'tcx>>,
255259

256260
pub(crate) clif_comments: crate::pretty_clif::CommentWriter,
257-
pub(crate) source_info_set: indexmap::IndexSet<SourceInfo>,
261+
262+
/// Last accessed source file and it's debuginfo file id.
263+
///
264+
/// For optimization purposes only
265+
pub(crate) last_source_file: Option<(Lrc<SourceFile>, FileId)>,
258266

259267
/// This should only be accessed by `CPlace::new_var`.
260268
pub(crate) next_ssa_var: u32,
@@ -338,8 +346,31 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> {
338346
}
339347

340348
pub(crate) fn set_debug_loc(&mut self, source_info: mir::SourceInfo) {
341-
let (index, _) = self.source_info_set.insert_full(source_info);
342-
self.bcx.set_srcloc(SourceLoc::new(index as u32));
349+
if let Some(debug_context) = &mut self.cx.debug_context {
350+
let (file, line, column) =
351+
DebugContext::get_span_loc(self.tcx, self.mir.span, source_info.span);
352+
353+
// add_source_file is very slow.
354+
// Optimize for the common case of the current file not being changed.
355+
let mut cached_file_id = None;
356+
if let Some((ref last_source_file, last_file_id)) = self.last_source_file {
357+
// If the allocations are not equal, the files may still be equal, but that
358+
// doesn't matter, as this is just an optimization.
359+
if rustc_data_structures::sync::Lrc::ptr_eq(last_source_file, &file) {
360+
cached_file_id = Some(last_file_id);
361+
}
362+
}
363+
364+
let file_id = if let Some(file_id) = cached_file_id {
365+
file_id
366+
} else {
367+
debug_context.add_source_file(&file)
368+
};
369+
370+
let source_loc =
371+
self.func_debug_cx.as_mut().unwrap().add_dbg_loc(file_id, line, column);
372+
self.bcx.set_srcloc(source_loc);
373+
}
343374
}
344375

345376
// Note: must be kept in sync with get_caller_location from cg_ssa

src/debuginfo/line_info.rs

Lines changed: 45 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -48,30 +48,6 @@ fn osstr_as_utf8_bytes(path: &OsStr) -> &[u8] {
4848
}
4949
}
5050

51-
fn get_span_loc(tcx: TyCtxt<'_>, function_span: Span, span: Span) -> (Lrc<SourceFile>, u64, u64) {
52-
// Based on https://github.com/rust-lang/rust/blob/e369d87b015a84653343032833d65d0545fd3f26/src/librustc_codegen_ssa/mir/mod.rs#L116-L131
53-
// In order to have a good line stepping behavior in debugger, we overwrite debug
54-
// locations of macro expansions with that of the outermost expansion site
55-
// (unless the crate is being compiled with `-Z debug-macros`).
56-
let span = if !span.from_expansion() || tcx.sess.opts.unstable_opts.debug_macros {
57-
span
58-
} else {
59-
// Walk up the macro expansion chain until we reach a non-expanded span.
60-
// We also stop at the function body level because no line stepping can occur
61-
// at the level above that.
62-
rustc_span::hygiene::walk_chain(span, function_span.ctxt())
63-
};
64-
65-
match tcx.sess.source_map().lookup_line(span.lo()) {
66-
Ok(SourceFileAndLine { sf: file, line }) => {
67-
let line_pos = file.line_begin_pos(span.lo());
68-
69-
(file, u64::try_from(line).unwrap() + 1, u64::from((span.lo() - line_pos).to_u32()) + 1)
70-
}
71-
Err(file) => (file, 0, 0),
72-
}
73-
}
74-
7551
const MD5_LEN: usize = 16;
7652

7753
fn make_file_info(hash: SourceFileHash) -> Option<FileInfo> {
@@ -85,6 +61,38 @@ fn make_file_info(hash: SourceFileHash) -> Option<FileInfo> {
8561
}
8662

8763
impl DebugContext {
64+
pub(crate) fn get_span_loc(
65+
tcx: TyCtxt<'_>,
66+
function_span: Span,
67+
span: Span,
68+
) -> (Lrc<SourceFile>, u64, u64) {
69+
// Based on https://github.com/rust-lang/rust/blob/e369d87b015a84653343032833d65d0545fd3f26/src/librustc_codegen_ssa/mir/mod.rs#L116-L131
70+
// In order to have a good line stepping behavior in debugger, we overwrite debug
71+
// locations of macro expansions with that of the outermost expansion site
72+
// (unless the crate is being compiled with `-Z debug-macros`).
73+
let span = if !span.from_expansion() || tcx.sess.opts.unstable_opts.debug_macros {
74+
span
75+
} else {
76+
// Walk up the macro expansion chain until we reach a non-expanded span.
77+
// We also stop at the function body level because no line stepping can occur
78+
// at the level above that.
79+
rustc_span::hygiene::walk_chain(span, function_span.ctxt())
80+
};
81+
82+
match tcx.sess.source_map().lookup_line(span.lo()) {
83+
Ok(SourceFileAndLine { sf: file, line }) => {
84+
let line_pos = file.line_begin_pos(span.lo());
85+
86+
(
87+
file,
88+
u64::try_from(line).unwrap() + 1,
89+
u64::from((span.lo() - line_pos).to_u32()) + 1,
90+
)
91+
}
92+
Err(file) => (file, 0, 0),
93+
}
94+
}
95+
8896
pub(crate) fn add_source_file(&mut self, source_file: &SourceFile) -> FileId {
8997
let line_program: &mut LineProgram = &mut self.dwarf.unit.line_program;
9098
let line_strings: &mut LineStringTable = &mut self.dwarf.line_strings;
@@ -124,63 +132,26 @@ impl DebugContext {
124132
}
125133

126134
impl FunctionDebugContext {
127-
pub(super) fn set_function_span(
128-
&mut self,
129-
debug_context: &mut DebugContext,
130-
tcx: TyCtxt<'_>,
131-
span: Span,
132-
) {
133-
let (file, line, column) = get_span_loc(tcx, span, span);
134-
135-
let file_id = debug_context.add_source_file(&file);
136-
137-
let entry = debug_context.dwarf.unit.get_mut(self.entry_id);
138-
entry.set(gimli::DW_AT_decl_file, AttributeValue::FileIndex(Some(file_id)));
139-
entry.set(gimli::DW_AT_decl_line, AttributeValue::Udata(line));
140-
entry.set(gimli::DW_AT_decl_column, AttributeValue::Udata(column));
135+
pub(crate) fn add_dbg_loc(&mut self, file_id: FileId, line: u64, column: u64) -> SourceLoc {
136+
let (index, _) = self.source_loc_set.insert_full((file_id, line, column));
137+
SourceLoc::new(u32::try_from(index).unwrap())
141138
}
142139

143140
pub(super) fn create_debug_lines(
144141
&mut self,
145142
debug_context: &mut DebugContext,
146-
tcx: TyCtxt<'_>,
147143
symbol: usize,
148144
context: &Context,
149-
function_span: Span,
150-
source_info_set: &indexmap::IndexSet<SourceInfo>,
151145
) -> CodeOffset {
152-
let mut last_span = None;
153-
let mut last_file = None;
154-
let mut create_row_for_span = |debug_context: &mut DebugContext, span: Span| {
155-
if let Some(last_span) = last_span {
156-
if span == last_span {
157-
debug_context.dwarf.unit.line_program.generate_row();
158-
return;
159-
}
160-
}
161-
last_span = Some(span);
162-
163-
let (file, line, col) = get_span_loc(tcx, function_span, span);
146+
let create_row_for_span =
147+
|debug_context: &mut DebugContext, source_loc: (FileId, u64, u64)| {
148+
let (file_id, line, col) = source_loc;
164149

165-
// line_program_add_file is very slow.
166-
// Optimize for the common case of the current file not being changed.
167-
let current_file_changed = if let Some(last_file) = &last_file {
168-
// If the allocations are not equal, then the files may still be equal, but that
169-
// is not a problem, as this is just an optimization.
170-
!rustc_data_structures::sync::Lrc::ptr_eq(last_file, &file)
171-
} else {
172-
true
173-
};
174-
if current_file_changed {
175-
let file_id = debug_context.add_source_file(&file);
176150
debug_context.dwarf.unit.line_program.row().file = file_id;
177-
last_file = Some(file);
178-
}
179-
180-
debug_context.dwarf.unit.line_program.row().line = line;
181-
debug_context.dwarf.unit.line_program.row().column = col;
182-
debug_context.dwarf.unit.line_program.generate_row();
183-
};
151+
debug_context.dwarf.unit.line_program.row().line = line;
152+
debug_context.dwarf.unit.line_program.row().column = col;
153+
debug_context.dwarf.unit.line_program.generate_row();
154+
};
184155

185156
debug_context
186157
.dwarf
@@ -194,10 +165,10 @@ impl FunctionDebugContext {
194165
for &MachSrcLoc { start, end, loc } in mcr.buffer.get_srclocs_sorted() {
195166
debug_context.dwarf.unit.line_program.row().address_offset = u64::from(start);
196167
if !loc.is_default() {
197-
let source_info = *source_info_set.get_index(loc.bits() as usize).unwrap();
198-
create_row_for_span(debug_context, source_info.span);
168+
let source_loc = *self.source_loc_set.get_index(loc.bits() as usize).unwrap();
169+
create_row_for_span(debug_context, source_loc);
199170
} else {
200-
create_row_for_span(debug_context, function_span);
171+
create_row_for_span(debug_context, self.function_source_loc);
201172
}
202173
func_end = end;
203174
}

src/debuginfo/mod.rs

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,11 @@ use cranelift_codegen::ir::Endianness;
1111
use cranelift_codegen::isa::TargetIsa;
1212

1313
use gimli::write::{
14-
Address, AttributeValue, DwarfUnit, LineProgram, LineString, Range, RangeList, UnitEntryId,
14+
Address, AttributeValue, DwarfUnit, FileId, LineProgram, LineString, Range, RangeList,
15+
UnitEntryId,
1516
};
1617
use gimli::{Encoding, Format, LineEncoding, RunTimeEndian};
18+
use indexmap::IndexSet;
1719

1820
pub(crate) use emit::{DebugReloc, DebugRelocName};
1921
pub(crate) use unwind::UnwindContext;
@@ -27,6 +29,8 @@ pub(crate) struct DebugContext {
2729

2830
pub(crate) struct FunctionDebugContext {
2931
entry_id: UnitEntryId,
32+
function_source_loc: (FileId, u64, u64),
33+
source_loc_set: indexmap::IndexSet<(FileId, u64, u64)>,
3034
}
3135

3236
impl DebugContext {
@@ -105,6 +109,10 @@ impl DebugContext {
105109
name: &str,
106110
function_span: Span,
107111
) -> FunctionDebugContext {
112+
let (file, line, column) = DebugContext::get_span_loc(tcx, function_span, function_span);
113+
114+
let file_id = self.add_source_file(&file);
115+
108116
// FIXME: add to appropriate scope instead of root
109117
let scope = self.dwarf.unit.root();
110118

@@ -115,34 +123,28 @@ impl DebugContext {
115123
entry.set(gimli::DW_AT_name, AttributeValue::StringRef(name_id));
116124
entry.set(gimli::DW_AT_linkage_name, AttributeValue::StringRef(name_id));
117125

118-
let mut function_debug_context = FunctionDebugContext { entry_id };
126+
entry.set(gimli::DW_AT_decl_file, AttributeValue::FileIndex(Some(file_id)));
127+
entry.set(gimli::DW_AT_decl_line, AttributeValue::Udata(line));
128+
entry.set(gimli::DW_AT_decl_column, AttributeValue::Udata(column));
119129

120-
function_debug_context.set_function_span(self, tcx, function_span);
121-
122-
function_debug_context
130+
FunctionDebugContext {
131+
entry_id,
132+
function_source_loc: (file_id, line, column),
133+
source_loc_set: IndexSet::new(),
134+
}
123135
}
124136
}
125137

126138
impl FunctionDebugContext {
127139
pub(crate) fn finalize(
128140
mut self,
129141
debug_context: &mut DebugContext,
130-
tcx: TyCtxt<'_>,
131142
func_id: FuncId,
132143
context: &Context,
133-
function_span: Span,
134-
source_info_set: &indexmap::IndexSet<SourceInfo>,
135144
) {
136145
let symbol = func_id.as_u32() as usize;
137146

138-
let end = self.create_debug_lines(
139-
debug_context,
140-
tcx,
141-
symbol,
142-
context,
143-
function_span,
144-
source_info_set,
145-
);
147+
let end = self.create_debug_lines(debug_context, symbol, context);
146148

147149
debug_context.unit_range_list.0.push(Range::StartLength {
148150
begin: Address::Symbol { symbol, addend: 0 },

0 commit comments

Comments
 (0)