Skip to content

Commit 5f5745b

Browse files
committed
coverage: Tidy up creation of covfun records
1 parent de53fe2 commit 5f5745b

File tree

2 files changed

+34
-32
lines changed

2 files changed

+34
-32
lines changed

Diff for: compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,10 @@ pub(crate) fn finalize(cx: &CodegenCx<'_, '_>) {
7575

7676
// Encode all filenames referenced by coverage mappings in this CGU.
7777
let filenames_buffer = global_file_table.make_filenames_buffer(tcx);
78-
let filenames_ref = llvm_cov::hash_bytes(&filenames_buffer);
78+
// The `llvm-cov` tool uses this hash to associate each covfun record with
79+
// its corresponding filenames table, since the final binary will typically
80+
// contain multiple covmap records from different compilation units.
81+
let filenames_hash = llvm_cov::hash_bytes(&filenames_buffer);
7982

8083
let mut unused_function_names = Vec::new();
8184

@@ -98,7 +101,7 @@ pub(crate) fn finalize(cx: &CodegenCx<'_, '_>) {
98101
for covfun in &covfun_records {
99102
unused_function_names.extend(covfun.mangled_function_name_if_unused());
100103

101-
covfun::generate_covfun_record(cx, filenames_ref, covfun)
104+
covfun::generate_covfun_record(cx, filenames_hash, covfun)
102105
}
103106

104107
// For unused functions, we need to take their mangled names and store them

Diff for: compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs

+29-30
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ fn fill_region_tables<'tcx>(
136136
/// as a global variable in the `__llvm_covfun` section.
137137
pub(crate) fn generate_covfun_record<'tcx>(
138138
cx: &CodegenCx<'_, 'tcx>,
139-
filenames_ref: u64,
139+
filenames_hash: u64,
140140
covfun: &CovfunRecord<'tcx>,
141141
) {
142142
let &CovfunRecord {
@@ -155,46 +155,45 @@ pub(crate) fn generate_covfun_record<'tcx>(
155155
regions,
156156
);
157157

158-
// Concatenate the encoded coverage mappings
159-
let coverage_mapping_size = coverage_mapping_buffer.len();
160-
let coverage_mapping_val = cx.const_bytes(&coverage_mapping_buffer);
161-
158+
// A covfun record consists of four target-endian integers, followed by the
159+
// encoded mapping data in bytes. Note that the length field is 32 bits.
160+
// <https://llvm.org/docs/CoverageMappingFormat.html#llvm-ir-representation>
161+
// See also `src/llvm-project/clang/lib/CodeGen/CoverageMappingGen.cpp` and
162+
// `COVMAP_V3` in `src/llvm-project/llvm/include/llvm/ProfileData/InstrProfData.inc`.
162163
let func_name_hash = llvm_cov::hash_bytes(mangled_function_name.as_bytes());
163-
let func_name_hash_val = cx.const_u64(func_name_hash);
164-
let coverage_mapping_size_val = cx.const_u32(coverage_mapping_size as u32);
165-
let source_hash_val = cx.const_u64(source_hash);
166-
let filenames_ref_val = cx.const_u64(filenames_ref);
167-
let func_record_val = cx.const_struct(
164+
let covfun_record = cx.const_struct(
168165
&[
169-
func_name_hash_val,
170-
coverage_mapping_size_val,
171-
source_hash_val,
172-
filenames_ref_val,
173-
coverage_mapping_val,
166+
cx.const_u64(func_name_hash),
167+
cx.const_u32(coverage_mapping_buffer.len() as u32),
168+
cx.const_u64(source_hash),
169+
cx.const_u64(filenames_hash),
170+
cx.const_bytes(&coverage_mapping_buffer),
174171
],
175-
/*packed=*/ true,
172+
// This struct needs to be packed, so that the 32-bit length field
173+
// doesn't have unexpected padding.
174+
true,
176175
);
177176

178177
// Choose a variable name to hold this function's covfun data.
179178
// Functions that are used have a suffix ("u") to distinguish them from
180179
// unused copies of the same function (from different CGUs), so that if a
181180
// linker sees both it won't discard the used copy's data.
182-
let func_record_var_name =
183-
CString::new(format!("__covrec_{:X}{}", func_name_hash, if is_used { "u" } else { "" }))
184-
.unwrap();
185-
debug!("function record var name: {:?}", func_record_var_name);
186-
187-
let llglobal = llvm::add_global(cx.llmod, cx.val_ty(func_record_val), &func_record_var_name);
188-
llvm::set_initializer(llglobal, func_record_val);
189-
llvm::set_global_constant(llglobal, true);
190-
llvm::set_linkage(llglobal, llvm::Linkage::LinkOnceODRLinkage);
191-
llvm::set_visibility(llglobal, llvm::Visibility::Hidden);
192-
llvm::set_section(llglobal, cx.covfun_section_name());
181+
let u = if is_used { "u" } else { "" };
182+
let covfun_var_name = CString::new(format!("__covrec_{func_name_hash:X}{u}")).unwrap();
183+
debug!("function record var name: {covfun_var_name:?}");
184+
185+
let covfun_global = llvm::add_global(cx.llmod, cx.val_ty(covfun_record), &covfun_var_name);
186+
llvm::set_initializer(covfun_global, covfun_record);
187+
llvm::set_global_constant(covfun_global, true);
188+
llvm::set_linkage(covfun_global, llvm::Linkage::LinkOnceODRLinkage);
189+
llvm::set_visibility(covfun_global, llvm::Visibility::Hidden);
190+
llvm::set_section(covfun_global, cx.covfun_section_name());
193191
// LLVM's coverage mapping format specifies 8-byte alignment for items in this section.
194192
// <https://llvm.org/docs/CoverageMappingFormat.html>
195-
llvm::set_alignment(llglobal, Align::EIGHT);
193+
llvm::set_alignment(covfun_global, Align::EIGHT);
196194
if cx.target_spec().supports_comdat() {
197-
llvm::set_comdat(cx.llmod, llglobal, &func_record_var_name);
195+
llvm::set_comdat(cx.llmod, covfun_global, &covfun_var_name);
198196
}
199-
cx.add_used_global(llglobal);
197+
198+
cx.add_used_global(covfun_global);
200199
}

0 commit comments

Comments
 (0)