coverage: Build the global file table on the fly
This commit is contained in:
parent
fe412af4fc
commit
154fae1e8d
3 changed files with 33 additions and 37 deletions
|
@ -1,6 +1,6 @@
|
||||||
use std::iter;
|
use std::iter;
|
||||||
|
|
||||||
use itertools::Itertools as _;
|
use itertools::Itertools;
|
||||||
use rustc_abi::Align;
|
use rustc_abi::Align;
|
||||||
use rustc_codegen_ssa::traits::{
|
use rustc_codegen_ssa::traits::{
|
||||||
BaseTypeCodegenMethods, ConstCodegenMethods, StaticCodegenMethods,
|
BaseTypeCodegenMethods, ConstCodegenMethods, StaticCodegenMethods,
|
||||||
|
@ -8,8 +8,8 @@ use rustc_codegen_ssa::traits::{
|
||||||
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
|
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
|
||||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||||
use rustc_index::IndexVec;
|
use rustc_index::IndexVec;
|
||||||
|
use rustc_middle::mir;
|
||||||
use rustc_middle::ty::{self, TyCtxt};
|
use rustc_middle::ty::{self, TyCtxt};
|
||||||
use rustc_middle::{bug, mir};
|
|
||||||
use rustc_session::RemapFileNameExt;
|
use rustc_session::RemapFileNameExt;
|
||||||
use rustc_session::config::RemapPathScopeComponents;
|
use rustc_session::config::RemapPathScopeComponents;
|
||||||
use rustc_span::def_id::DefIdSet;
|
use rustc_span::def_id::DefIdSet;
|
||||||
|
@ -67,25 +67,21 @@ pub(crate) fn finalize(cx: &CodegenCx<'_, '_>) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let all_file_names = function_coverage_map
|
// The order of entries in this global file table needs to be deterministic,
|
||||||
.iter()
|
// and ideally should also be independent of the details of stable-hashing,
|
||||||
.map(|(_, fn_cov)| fn_cov.function_coverage_info.body_span)
|
// because coverage tests snapshots (`.cov-map`) can observe the order and
|
||||||
.map(|span| span_file_name(tcx, span));
|
// would need to be re-blessed if it changes. As long as those requirements
|
||||||
let global_file_table = GlobalFileTable::new(all_file_names);
|
// are satisfied, the order can be arbitrary.
|
||||||
|
let mut global_file_table = GlobalFileTable::new();
|
||||||
// Encode all filenames referenced by coverage mappings in this CGU.
|
|
||||||
let filenames_buffer = global_file_table.make_filenames_buffer(tcx);
|
|
||||||
// The `llvm-cov` tool uses this hash to associate each covfun record with
|
|
||||||
// its corresponding filenames table, since the final binary will typically
|
|
||||||
// contain multiple covmap records from different compilation units.
|
|
||||||
let filenames_hash = llvm_cov::hash_bytes(&filenames_buffer);
|
|
||||||
|
|
||||||
let mut unused_function_names = Vec::new();
|
|
||||||
|
|
||||||
let covfun_records = function_coverage_map
|
let covfun_records = function_coverage_map
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
// Sort by symbol name, so that the global file table is built in an
|
||||||
|
// order that doesn't depend on the stable-hash-based order in which
|
||||||
|
// instances were visited during codegen.
|
||||||
|
.sorted_by_cached_key(|&(instance, _)| tcx.symbol_name(instance).name)
|
||||||
.filter_map(|(instance, function_coverage)| {
|
.filter_map(|(instance, function_coverage)| {
|
||||||
prepare_covfun_record(tcx, &global_file_table, instance, &function_coverage)
|
prepare_covfun_record(tcx, &mut global_file_table, instance, &function_coverage)
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
@ -98,6 +94,15 @@ pub(crate) fn finalize(cx: &CodegenCx<'_, '_>) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Encode all filenames referenced by coverage mappings in this CGU.
|
||||||
|
let filenames_buffer = global_file_table.make_filenames_buffer(tcx);
|
||||||
|
// The `llvm-cov` tool uses this hash to associate each covfun record with
|
||||||
|
// its corresponding filenames table, since the final binary will typically
|
||||||
|
// contain multiple covmap records from different compilation units.
|
||||||
|
let filenames_hash = llvm_cov::hash_bytes(&filenames_buffer);
|
||||||
|
|
||||||
|
let mut unused_function_names = vec![];
|
||||||
|
|
||||||
for covfun in &covfun_records {
|
for covfun in &covfun_records {
|
||||||
unused_function_names.extend(covfun.mangled_function_name_if_unused());
|
unused_function_names.extend(covfun.mangled_function_name_if_unused());
|
||||||
|
|
||||||
|
@ -137,22 +142,13 @@ struct GlobalFileTable {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GlobalFileTable {
|
impl GlobalFileTable {
|
||||||
fn new(all_file_names: impl IntoIterator<Item = Symbol>) -> Self {
|
fn new() -> Self {
|
||||||
// Collect all of the filenames into a set. Filenames usually come in
|
Self { raw_file_table: FxIndexSet::default() }
|
||||||
// contiguous runs, so we can dedup adjacent ones to save work.
|
|
||||||
let mut raw_file_table = all_file_names.into_iter().dedup().collect::<FxIndexSet<Symbol>>();
|
|
||||||
|
|
||||||
// Sort the file table by its actual string values, not the arbitrary
|
|
||||||
// ordering of its symbols.
|
|
||||||
raw_file_table.sort_unstable_by(|a, b| a.as_str().cmp(b.as_str()));
|
|
||||||
|
|
||||||
Self { raw_file_table }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn global_file_id_for_file_name(&self, file_name: Symbol) -> GlobalFileId {
|
fn global_file_id_for_file_name(&mut self, file_name: Symbol) -> GlobalFileId {
|
||||||
let raw_id = self.raw_file_table.get_index_of(&file_name).unwrap_or_else(|| {
|
// Ensure the given file has a table entry, and get its index.
|
||||||
bug!("file name not found in prepared global file table: {file_name}");
|
let (raw_id, _) = self.raw_file_table.insert_full(file_name);
|
||||||
});
|
|
||||||
// The raw file table doesn't include an entry for the working dir
|
// The raw file table doesn't include an entry for the working dir
|
||||||
// (which has ID 0), so add 1 to get the correct ID.
|
// (which has ID 0), so add 1 to get the correct ID.
|
||||||
GlobalFileId::from_usize(raw_id + 1)
|
GlobalFileId::from_usize(raw_id + 1)
|
||||||
|
|
|
@ -45,7 +45,7 @@ impl<'tcx> CovfunRecord<'tcx> {
|
||||||
|
|
||||||
pub(crate) fn prepare_covfun_record<'tcx>(
|
pub(crate) fn prepare_covfun_record<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
global_file_table: &GlobalFileTable,
|
global_file_table: &mut GlobalFileTable,
|
||||||
instance: Instance<'tcx>,
|
instance: Instance<'tcx>,
|
||||||
function_coverage: &FunctionCoverage<'tcx>,
|
function_coverage: &FunctionCoverage<'tcx>,
|
||||||
) -> Option<CovfunRecord<'tcx>> {
|
) -> Option<CovfunRecord<'tcx>> {
|
||||||
|
@ -75,7 +75,7 @@ pub(crate) fn prepare_covfun_record<'tcx>(
|
||||||
/// Populates the mapping region tables in the current function's covfun record.
|
/// Populates the mapping region tables in the current function's covfun record.
|
||||||
fn fill_region_tables<'tcx>(
|
fn fill_region_tables<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
global_file_table: &GlobalFileTable,
|
global_file_table: &mut GlobalFileTable,
|
||||||
function_coverage: &FunctionCoverage<'tcx>,
|
function_coverage: &FunctionCoverage<'tcx>,
|
||||||
covfun: &mut CovfunRecord<'tcx>,
|
covfun: &mut CovfunRecord<'tcx>,
|
||||||
) {
|
) {
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
Function name: unused_mod::main
|
Function name: unused_mod::main
|
||||||
Raw bytes (9): 0x[01, 02, 00, 01, 01, 04, 01, 02, 02]
|
Raw bytes (9): 0x[01, 01, 00, 01, 01, 04, 01, 02, 02]
|
||||||
Number of files: 1
|
Number of files: 1
|
||||||
- file 0 => global file 2
|
- file 0 => global file 1
|
||||||
Number of expressions: 0
|
Number of expressions: 0
|
||||||
Number of file 0 mappings: 1
|
Number of file 0 mappings: 1
|
||||||
- Code(Counter(0)) at (prev + 4, 1) to (start + 2, 2)
|
- Code(Counter(0)) at (prev + 4, 1) to (start + 2, 2)
|
||||||
Highest counter ID seen: c0
|
Highest counter ID seen: c0
|
||||||
|
|
||||||
Function name: unused_mod::unused_module::never_called_function (unused)
|
Function name: unused_mod::unused_module::never_called_function (unused)
|
||||||
Raw bytes (9): 0x[01, 01, 00, 01, 00, 02, 01, 02, 02]
|
Raw bytes (9): 0x[01, 02, 00, 01, 00, 02, 01, 02, 02]
|
||||||
Number of files: 1
|
Number of files: 1
|
||||||
- file 0 => global file 1
|
- file 0 => global file 2
|
||||||
Number of expressions: 0
|
Number of expressions: 0
|
||||||
Number of file 0 mappings: 1
|
Number of file 0 mappings: 1
|
||||||
- Code(Zero) at (prev + 2, 1) to (start + 2, 2)
|
- Code(Zero) at (prev + 2, 1) to (start + 2, 2)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue