Skip to content

Commit

Permalink
coverage: Emit the filenames section before encoding per-function map…
Browse files Browse the repository at this point in the history
…pings

Most coverage metadata is encoded into two sections in the final executable.
The `__llvm_covmap` section mostly just contains a list of filenames, while the
`__llvm_covfun` section contains encoded coverage maps for each instrumented
function.

The catch is that each per-function record also needs to contain a hash of the
filenames list that it refers to. Historically this was handled by assembling
most of the per-function data into a temporary list, then assembling the
filenames buffer, then using the filenames hash to emit the per-function data,
and then finally emitting the filenames table itself.

However, now that we build the filenames table up-front (via a separate
traversal of the per-function data), we can hash and emit that part first, and
then emit each of the per-function records immediately after building. This
removes the awkwardness of having to temporarily store nearly-complete
per-function records.
  • Loading branch information
Zalathar committed Oct 22, 2023
1 parent de4cfbc commit c46abe4
Showing 1 changed file with 15 additions and 21 deletions.
36 changes: 15 additions & 21 deletions compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,22 @@ pub fn finalize(cx: &CodegenCx<'_, '_>) {
function_coverage_entries.iter().flat_map(|(_, fn_cov)| fn_cov.all_file_names());
let global_file_table = GlobalFileTable::new(all_file_names);

// Encode all filenames referenced by coverage mappings in this CGU.
let filenames_buffer = global_file_table.make_filenames_buffer(tcx);

let filenames_size = filenames_buffer.len();
let filenames_val = cx.const_bytes(&filenames_buffer);
let filenames_ref = coverageinfo::hash_bytes(&filenames_buffer);

// Generate the coverage map header, which contains the filenames used by
// this CGU's coverage mappings, and store it in a well-known global.
let cov_data_val = generate_coverage_map(cx, version, filenames_size, filenames_val);
coverageinfo::save_cov_data_to_mod(cx, cov_data_val);

let mut unused_function_names = Vec::new();
let covfun_section_name = coverageinfo::covfun_section_name(cx);

// Encode coverage mappings and generate function records
let mut function_data = Vec::new();
for (instance, function_coverage) in function_coverage_entries {
debug!("Generate function coverage for {}, {:?}", cx.codegen_unit.name(), instance);

Expand All @@ -91,23 +105,6 @@ pub fn finalize(cx: &CodegenCx<'_, '_>) {
}
}

function_data.push((mangled_function_name, source_hash, is_used, coverage_mapping_buffer));
}

// Encode all filenames referenced by counters/expressions in this module
let filenames_buffer = global_file_table.make_filenames_buffer(tcx);

let filenames_size = filenames_buffer.len();
let filenames_val = cx.const_bytes(&filenames_buffer);
let filenames_ref = coverageinfo::hash_bytes(&filenames_buffer);

// Generate the LLVM IR representation of the coverage map and store it in a well-known global
let cov_data_val = generate_coverage_map(cx, version, filenames_size, filenames_val);

let mut unused_function_names = Vec::new();

let covfun_section_name = coverageinfo::covfun_section_name(cx);
for (mangled_function_name, source_hash, is_used, coverage_mapping_buffer) in function_data {
if !is_used {
unused_function_names.push(mangled_function_name);
}
Expand Down Expand Up @@ -141,9 +138,6 @@ pub fn finalize(cx: &CodegenCx<'_, '_>) {
llvm::set_linkage(array, llvm::Linkage::InternalLinkage);
llvm::set_initializer(array, initializer);
}

// Save the coverage data value to LLVM IR
coverageinfo::save_cov_data_to_mod(cx, cov_data_val);
}

/// Maps "global" (per-CGU) file ID numbers to their underlying filenames.
Expand Down

0 comments on commit c46abe4

Please sign in to comment.