Skip to content

Commit 837a25d

Browse files
committed
coverage: Identify source files by ID, not by interned filename
1 parent 34ed51c commit 837a25d

File tree

3 files changed

+33
-37
lines changed

3 files changed

+33
-37
lines changed

compiler/rustc_codegen_llvm/src/coverageinfo/llvm_cov.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,10 @@ pub(crate) fn create_pgo_func_name_var<'ll>(
4040
}
4141
}
4242

43-
pub(crate) fn write_filenames_to_buffer<'a>(
44-
filenames: impl IntoIterator<Item = &'a str>,
45-
) -> Vec<u8> {
43+
pub(crate) fn write_filenames_to_buffer(filenames: &[impl AsRef<str>]) -> Vec<u8> {
4644
let (pointers, lengths) = filenames
4745
.into_iter()
46+
.map(AsRef::as_ref)
4847
.map(|s: &str| (s.as_c_char_ptr(), s.len()))
4948
.unzip::<_, _, Vec<_>, Vec<_>>();
5049

compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs

+28-29
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
1-
use std::iter;
1+
use std::sync::Arc;
22

33
use itertools::Itertools;
44
use rustc_abi::Align;
55
use rustc_codegen_ssa::traits::{
66
BaseTypeCodegenMethods, ConstCodegenMethods, StaticCodegenMethods,
77
};
8-
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
8+
use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
99
use rustc_hir::def_id::{DefId, LocalDefId};
1010
use rustc_index::IndexVec;
1111
use rustc_middle::mir;
1212
use rustc_middle::ty::{self, TyCtxt};
1313
use rustc_session::RemapFileNameExt;
1414
use rustc_session::config::RemapPathScopeComponents;
1515
use rustc_span::def_id::DefIdSet;
16-
use rustc_span::{Span, Symbol};
16+
use rustc_span::{SourceFile, StableSourceFileId};
1717
use tracing::debug;
1818

1919
use crate::common::CodegenCx;
@@ -132,45 +132,51 @@ pub(crate) fn finalize(cx: &CodegenCx<'_, '_>) {
132132
generate_covmap_record(cx, covmap_version, &filenames_buffer);
133133
}
134134

135-
/// Maps "global" (per-CGU) file ID numbers to their underlying filenames.
135+
/// Maps "global" (per-CGU) file ID numbers to their underlying source files.
136136
struct GlobalFileTable {
137-
/// This "raw" table doesn't include the working dir, so a filename's
137+
/// This "raw" table doesn't include the working dir, so a file's
138138
/// global ID is its index in this set **plus one**.
139-
raw_file_table: FxIndexSet<Symbol>,
139+
raw_file_table: FxIndexMap<StableSourceFileId, Arc<SourceFile>>,
140140
}
141141

142142
impl GlobalFileTable {
143143
fn new() -> Self {
144-
Self { raw_file_table: FxIndexSet::default() }
144+
Self { raw_file_table: FxIndexMap::default() }
145145
}
146146

147-
fn global_file_id_for_file_name(&mut self, file_name: Symbol) -> GlobalFileId {
147+
fn global_file_id_for_file(&mut self, file: &Arc<SourceFile>) -> GlobalFileId {
148148
// Ensure the given file has a table entry, and get its index.
149-
let (raw_id, _) = self.raw_file_table.insert_full(file_name);
149+
let entry = self.raw_file_table.entry(file.stable_id);
150+
let raw_id = entry.index();
151+
entry.or_insert_with(|| Arc::clone(file));
152+
150153
// The raw file table doesn't include an entry for the working dir
151154
// (which has ID 0), so add 1 to get the correct ID.
152155
GlobalFileId::from_usize(raw_id + 1)
153156
}
154157

155158
fn make_filenames_buffer(&self, tcx: TyCtxt<'_>) -> Vec<u8> {
159+
let mut table = Vec::with_capacity(self.raw_file_table.len() + 1);
160+
156161
// LLVM Coverage Mapping Format version 6 (zero-based encoded as 5)
157162
// requires setting the first filename to the compilation directory.
158163
// Since rustc generates coverage maps with relative paths, the
159164
// compilation directory can be combined with the relative paths
160165
// to get absolute paths, if needed.
161-
use rustc_session::RemapFileNameExt;
162-
use rustc_session::config::RemapPathScopeComponents;
163-
let working_dir: &str = &tcx
164-
.sess
165-
.opts
166-
.working_dir
167-
.for_scope(tcx.sess, RemapPathScopeComponents::MACRO)
168-
.to_string_lossy();
169-
170-
// Insert the working dir at index 0, before the other filenames.
171-
let filenames =
172-
iter::once(working_dir).chain(self.raw_file_table.iter().map(Symbol::as_str));
173-
llvm_cov::write_filenames_to_buffer(filenames)
166+
table.push(
167+
tcx.sess
168+
.opts
169+
.working_dir
170+
.for_scope(tcx.sess, RemapPathScopeComponents::MACRO)
171+
.to_string_lossy(),
172+
);
173+
174+
// Add the regular entries after the base directory.
175+
table.extend(self.raw_file_table.values().map(|file| {
176+
file.name.for_scope(tcx.sess, RemapPathScopeComponents::MACRO).to_string_lossy()
177+
}));
178+
179+
llvm_cov::write_filenames_to_buffer(&table)
174180
}
175181
}
176182

@@ -209,13 +215,6 @@ impl VirtualFileMapping {
209215
}
210216
}
211217

212-
fn span_file_name(tcx: TyCtxt<'_>, span: Span) -> Symbol {
213-
let source_file = tcx.sess.source_map().lookup_source_file(span.lo());
214-
let name =
215-
source_file.name.for_scope(tcx.sess, RemapPathScopeComponents::MACRO).to_string_lossy();
216-
Symbol::intern(&name)
217-
}
218-
219218
/// Generates the contents of the covmap record for this CGU, which mostly
220219
/// consists of a header and a list of filenames. The record is then stored
221220
/// as a global variable in the `__llvm_covmap` section.

compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs

+3-5
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use rustc_target::spec::HasTargetSpec;
1919
use tracing::debug;
2020

2121
use crate::common::CodegenCx;
22-
use crate::coverageinfo::mapgen::{GlobalFileTable, VirtualFileMapping, span_file_name, spans};
22+
use crate::coverageinfo::mapgen::{GlobalFileTable, VirtualFileMapping, spans};
2323
use crate::coverageinfo::{ffi, llvm_cov};
2424
use crate::llvm;
2525

@@ -117,16 +117,14 @@ fn fill_region_tables<'tcx>(
117117
covfun: &mut CovfunRecord<'tcx>,
118118
) {
119119
// Currently a function's mappings must all be in the same file as its body span.
120-
let file_name = span_file_name(tcx, fn_cov_info.body_span);
121120
let source_map = tcx.sess.source_map();
122121
let source_file = source_map.lookup_source_file(fn_cov_info.body_span.lo());
123122

124-
// Look up the global file ID for that filename.
125-
let global_file_id = global_file_table.global_file_id_for_file_name(file_name);
123+
// Look up the global file ID for that file.
124+
let global_file_id = global_file_table.global_file_id_for_file(&source_file);
126125

127126
// Associate that global file ID with a local file ID for this function.
128127
let local_file_id = covfun.virtual_file_mapping.local_id_for_global(global_file_id);
129-
debug!(" file id: {local_file_id:?} => {global_file_id:?} = '{file_name:?}'");
130128

131129
let ffi::Regions { code_regions, branch_regions, mcdc_branch_regions, mcdc_decision_regions } =
132130
&mut covfun.regions;

0 commit comments

Comments
 (0)