diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs index 5da7848b39c..39fb0aeed07 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs @@ -19,6 +19,7 @@ use tracing::debug; use crate::common::CodegenCx; use crate::coverageinfo::llvm_cov; use crate::coverageinfo::map_data::FunctionCoverage; +use crate::coverageinfo::mapgen::covfun::prepare_covfun_record; use crate::llvm; mod covfun; @@ -85,16 +86,17 @@ pub(crate) fn finalize(cx: &CodegenCx<'_, '_>) { let mut unused_function_names = Vec::new(); - // Encode coverage mappings and generate function records - for (instance, function_coverage) in function_coverage_map { - covfun::prepare_and_generate_covfun_record( - cx, - &global_file_table, - filenames_ref, - &mut unused_function_names, - instance, - &function_coverage, - ); + let covfun_records = function_coverage_map + .into_iter() + .filter_map(|(instance, function_coverage)| { + prepare_covfun_record(tcx, &global_file_table, instance, &function_coverage) + }) + .collect::>(); + + for covfun in &covfun_records { + unused_function_names.extend(covfun.mangled_function_name_if_unused()); + + covfun::generate_covfun_record(cx, filenames_ref, covfun) } // For unused functions, we need to take their mangled names and store them diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs index aaa6bbcdfc9..a68b026a4c0 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs @@ -22,16 +22,30 @@ use crate::coverageinfo::mapgen::{GlobalFileTable, VirtualFileMapping, span_file use crate::coverageinfo::{ffi, llvm_cov}; use crate::llvm; -pub(crate) fn prepare_and_generate_covfun_record<'ll, 'tcx>( - cx: &CodegenCx<'ll, 'tcx>, +/// Intermediate coverage metadata for a single function, used to help build +/// the final record that will be embedded in the `__llvm_covfun` section. +#[derive(Debug)] +pub(crate) struct CovfunRecord<'tcx> { + mangled_function_name: &'tcx str, + source_hash: u64, + is_used: bool, + coverage_mapping_buffer: Vec, +} + +impl<'tcx> CovfunRecord<'tcx> { + /// FIXME(Zalathar): Make this the responsibility of the code that determines + /// which functions are unused. + pub(crate) fn mangled_function_name_if_unused(&self) -> Option<&'tcx str> { + (!self.is_used).then_some(self.mangled_function_name) + } +} + +pub(crate) fn prepare_covfun_record<'tcx>( + tcx: TyCtxt<'tcx>, global_file_table: &GlobalFileTable, - filenames_ref: u64, - unused_function_names: &mut Vec<&'tcx str>, instance: Instance<'tcx>, function_coverage: &FunctionCoverage<'tcx>, -) { - let tcx = cx.tcx; - +) -> Option> { let mangled_function_name = tcx.symbol_name(instance).name; let source_hash = function_coverage.source_hash(); let is_used = function_coverage.is_used(); @@ -47,22 +61,11 @@ pub(crate) fn prepare_and_generate_covfun_record<'ll, 'tcx>( ); } else { debug!("unused function had no coverage mapping data: {}", mangled_function_name); - return; + return None; } } - if !is_used { - unused_function_names.push(mangled_function_name); - } - - generate_covfun_record( - cx, - mangled_function_name, - source_hash, - filenames_ref, - coverage_mapping_buffer, - is_used, - ); + Some(CovfunRecord { mangled_function_name, source_hash, is_used, coverage_mapping_buffer }) } /// Using the expressions and counter regions collected for a single function, @@ -145,14 +148,18 @@ fn encode_mappings_for_function( /// Generates the contents of the covfun record for this function, which /// contains the function's coverage mapping data. The record is then stored /// as a global variable in the `__llvm_covfun` section. -fn generate_covfun_record( - cx: &CodegenCx<'_, '_>, - mangled_function_name: &str, - source_hash: u64, +pub(crate) fn generate_covfun_record<'tcx>( + cx: &CodegenCx<'_, 'tcx>, filenames_ref: u64, - coverage_mapping_buffer: Vec, - is_used: bool, + covfun: &CovfunRecord<'tcx>, ) { + let &CovfunRecord { + mangled_function_name, + source_hash, + is_used, + ref coverage_mapping_buffer, // Previously-encoded coverage mappings + } = covfun; + // Concatenate the encoded coverage mappings let coverage_mapping_size = coverage_mapping_buffer.len(); let coverage_mapping_val = cx.const_bytes(&coverage_mapping_buffer);