about summary refs log tree commit diff
path: root/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs
diff options
context:
space:
mode:
authorZalathar <Zalathar@users.noreply.github.com>2024-12-11 15:41:02 +1100
committerZalathar <Zalathar@users.noreply.github.com>2024-12-11 21:35:45 +1100
commit3f3a9bf7f50afbfde72cd0b9479323dddc84fe6d (patch)
tree9aeeae3bc9516d499202142127bccb1d520bb95c /compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs
parent512f3fdebe72532a435238435f0e16eff61fbf38 (diff)
downloadrust-3f3a9bf7f50afbfde72cd0b9479323dddc84fe6d.tar.gz
rust-3f3a9bf7f50afbfde72cd0b9479323dddc84fe6d.zip
coverage: Store intermediate region tables in `CovfunRecord`
This defers the call to `llvm_cov::write_function_mappings_to_buffer` until
just before its enclosing global variable is created.
Diffstat (limited to 'compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs')
-rw-r--r--compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs87
1 files changed, 41 insertions, 46 deletions
diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs
index a68b026a4c0..530e6827f55 100644
--- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs
+++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs
@@ -29,7 +29,10 @@ pub(crate) struct CovfunRecord<'tcx> {
     mangled_function_name: &'tcx str,
     source_hash: u64,
     is_used: bool,
-    coverage_mapping_buffer: Vec<u8>,
+
+    virtual_file_mapping: VirtualFileMapping,
+    expressions: Vec<ffi::CounterExpression>,
+    regions: ffi::Regions,
 }
 
 impl<'tcx> CovfunRecord<'tcx> {
@@ -46,51 +49,41 @@ pub(crate) fn prepare_covfun_record<'tcx>(
     instance: Instance<'tcx>,
     function_coverage: &FunctionCoverage<'tcx>,
 ) -> Option<CovfunRecord<'tcx>> {
-    let mangled_function_name = tcx.symbol_name(instance).name;
-    let source_hash = function_coverage.source_hash();
-    let is_used = function_coverage.is_used();
-
-    let coverage_mapping_buffer =
-        encode_mappings_for_function(tcx, global_file_table, function_coverage);
-
-    if coverage_mapping_buffer.is_empty() {
-        if function_coverage.is_used() {
-            bug!(
-                "A used function should have had coverage mapping data but did not: {}",
-                mangled_function_name
-            );
+    let mut covfun = CovfunRecord {
+        mangled_function_name: tcx.symbol_name(instance).name,
+        source_hash: function_coverage.source_hash(),
+        is_used: function_coverage.is_used(),
+        virtual_file_mapping: VirtualFileMapping::default(),
+        expressions: function_coverage.counter_expressions().collect::<Vec<_>>(),
+        regions: ffi::Regions::default(),
+    };
+
+    fill_region_tables(tcx, global_file_table, function_coverage, &mut covfun);
+
+    if covfun.regions.has_no_regions() {
+        if covfun.is_used {
+            bug!("a used function should have had coverage mapping data but did not: {covfun:?}");
         } else {
-            debug!("unused function had no coverage mapping data: {}", mangled_function_name);
+            debug!(?covfun, "unused function had no coverage mapping data");
             return None;
         }
     }
 
-    Some(CovfunRecord { mangled_function_name, source_hash, is_used, coverage_mapping_buffer })
+    Some(covfun)
 }
 
-/// Using the expressions and counter regions collected for a single function,
-/// generate the variable-sized payload of its corresponding `__llvm_covfun`
-/// entry. The payload is returned as a vector of bytes.
-///
-/// Newly-encountered filenames will be added to the global file table.
-fn encode_mappings_for_function(
-    tcx: TyCtxt<'_>,
+/// Populates the mapping region tables in the current function's covfun record.
+fn fill_region_tables<'tcx>(
+    tcx: TyCtxt<'tcx>,
     global_file_table: &GlobalFileTable,
-    function_coverage: &FunctionCoverage<'_>,
-) -> Vec<u8> {
+    function_coverage: &FunctionCoverage<'tcx>,
+    covfun: &mut CovfunRecord<'tcx>,
+) {
     let counter_regions = function_coverage.counter_regions();
     if counter_regions.is_empty() {
-        return Vec::new();
+        return;
     }
 
-    let expressions = function_coverage.counter_expressions().collect::<Vec<_>>();
-
-    let mut virtual_file_mapping = VirtualFileMapping::default();
-    let mut code_regions = vec![];
-    let mut branch_regions = vec![];
-    let mut mcdc_branch_regions = vec![];
-    let mut mcdc_decision_regions = vec![];
-
     // Currently a function's mappings must all be in the same file as its body span.
     let file_name = span_file_name(tcx, function_coverage.function_coverage_info.body_span);
 
@@ -98,9 +91,12 @@ fn encode_mappings_for_function(
     let global_file_id = global_file_table.global_file_id_for_file_name(file_name);
 
     // Associate that global file ID with a local file ID for this function.
-    let local_file_id = virtual_file_mapping.local_id_for_global(global_file_id);
+    let local_file_id = covfun.virtual_file_mapping.local_id_for_global(global_file_id);
     debug!("  file id: {local_file_id:?} => {global_file_id:?} = '{file_name:?}'");
 
+    let ffi::Regions { code_regions, branch_regions, mcdc_branch_regions, mcdc_decision_regions } =
+        &mut covfun.regions;
+
     // For each counter/region pair in this function+file, convert it to a
     // form suitable for FFI.
     for (mapping_kind, region) in counter_regions {
@@ -133,16 +129,6 @@ fn encode_mappings_for_function(
             }
         }
     }
-
-    // Encode the function's coverage mappings into a buffer.
-    llvm_cov::write_function_mappings_to_buffer(
-        &virtual_file_mapping.into_vec(),
-        &expressions,
-        &code_regions,
-        &branch_regions,
-        &mcdc_branch_regions,
-        &mcdc_decision_regions,
-    )
 }
 
 /// Generates the contents of the covfun record for this function, which
@@ -157,9 +143,18 @@ pub(crate) fn generate_covfun_record<'tcx>(
         mangled_function_name,
         source_hash,
         is_used,
-        ref coverage_mapping_buffer, // Previously-encoded coverage mappings
+        ref virtual_file_mapping,
+        ref expressions,
+        ref regions,
     } = covfun;
 
+    // Encode the function's coverage mappings into a buffer.
+    let coverage_mapping_buffer = llvm_cov::write_function_mappings_to_buffer(
+        &virtual_file_mapping.to_vec(),
+        expressions,
+        regions,
+    );
+
     // Concatenate the encoded coverage mappings
     let coverage_mapping_size = coverage_mapping_buffer.len();
     let coverage_mapping_val = cx.const_bytes(&coverage_mapping_buffer);