Skip to content

Commit 267d1d5

Browse files
committed
coverage: Emit the filenames section before encoding per-function mappings
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.
1 parent a61e358 commit 267d1d5

File tree

1 file changed

+13
-21
lines changed
  • compiler/rustc_codegen_llvm/src/coverageinfo

1 file changed

+13
-21
lines changed

compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs

+13-21
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,20 @@ pub fn finalize(cx: &CodegenCx<'_, '_>) {
6868
function_coverage_entries.iter().flat_map(|(_, fn_cov)| fn_cov.all_file_names());
6969
let global_file_table = GlobalFileTable::new(tcx, all_file_names);
7070

71+
// Encode all filenames referenced by counters/expressions in this module
72+
let filenames_buffer = global_file_table.filenames_buffer();
73+
let filenames_size = filenames_buffer.len();
74+
let filenames_val = cx.const_bytes(filenames_buffer);
75+
let filenames_ref = coverageinfo::hash_bytes(filenames_buffer);
76+
77+
// Generate the LLVM IR representation of the coverage map and store it in a well-known global
78+
let cov_data_val = generate_coverage_map(cx, version, filenames_size, filenames_val);
79+
coverageinfo::save_cov_data_to_mod(cx, cov_data_val);
80+
81+
let mut unused_function_names = Vec::new();
82+
let covfun_section_name = coverageinfo::covfun_section_name(cx);
83+
7184
// Encode coverage mappings and generate function records
72-
let mut function_data = Vec::new();
7385
for (instance, function_coverage) in function_coverage_entries {
7486
debug!("Generate function coverage for {}, {:?}", cx.codegen_unit.name(), instance);
7587

@@ -92,23 +104,6 @@ pub fn finalize(cx: &CodegenCx<'_, '_>) {
92104
}
93105
}
94106

95-
function_data.push((mangled_function_name, source_hash, is_used, coverage_mapping_buffer));
96-
}
97-
98-
// Encode all filenames referenced by counters/expressions in this module
99-
let filenames_buffer = global_file_table.filenames_buffer();
100-
101-
let filenames_size = filenames_buffer.len();
102-
let filenames_val = cx.const_bytes(filenames_buffer);
103-
let filenames_ref = coverageinfo::hash_bytes(filenames_buffer);
104-
105-
// Generate the LLVM IR representation of the coverage map and store it in a well-known global
106-
let cov_data_val = generate_coverage_map(cx, version, filenames_size, filenames_val);
107-
108-
let mut unused_function_names = Vec::new();
109-
110-
let covfun_section_name = coverageinfo::covfun_section_name(cx);
111-
for (mangled_function_name, source_hash, is_used, coverage_mapping_buffer) in function_data {
112107
if !is_used {
113108
unused_function_names.push(mangled_function_name);
114109
}
@@ -142,9 +137,6 @@ pub fn finalize(cx: &CodegenCx<'_, '_>) {
142137
llvm::set_linkage(array, llvm::Linkage::InternalLinkage);
143138
llvm::set_initializer(array, initializer);
144139
}
145-
146-
// Save the coverage data value to LLVM IR
147-
coverageinfo::save_cov_data_to_mod(cx, cov_data_val);
148140
}
149141

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

0 commit comments

Comments
 (0)