coverage: Obtain the __llvm_covfun
section name outside a per-function loop
This section name is always constant for a given target, but obtaining it from LLVM requires a few intermediate allocations. There's no need to do so repeatedly from inside a per-function loop.
This commit is contained in:
parent
155a5c2862
commit
01f3cc1272
2 changed files with 31 additions and 8 deletions
|
@ -100,9 +100,11 @@ pub fn finalize(cx: &CodegenCx<'_, '_>) {
|
||||||
// Generate the LLVM IR representation of the coverage map and store it in a well-known global
|
// Generate the LLVM IR representation of the coverage map and store it in a well-known global
|
||||||
let cov_data_val = mapgen.generate_coverage_map(cx, version, filenames_size, filenames_val);
|
let cov_data_val = mapgen.generate_coverage_map(cx, version, filenames_size, filenames_val);
|
||||||
|
|
||||||
|
let covfun_section_name = coverageinfo::covfun_section_name(cx);
|
||||||
for (mangled_function_name, source_hash, is_used, coverage_mapping_buffer) in function_data {
|
for (mangled_function_name, source_hash, is_used, coverage_mapping_buffer) in function_data {
|
||||||
save_function_record(
|
save_function_record(
|
||||||
cx,
|
cx,
|
||||||
|
&covfun_section_name,
|
||||||
mangled_function_name,
|
mangled_function_name,
|
||||||
source_hash,
|
source_hash,
|
||||||
filenames_ref,
|
filenames_ref,
|
||||||
|
@ -228,6 +230,7 @@ impl CoverageMapGenerator {
|
||||||
/// specific, well-known section and name.
|
/// specific, well-known section and name.
|
||||||
fn save_function_record(
|
fn save_function_record(
|
||||||
cx: &CodegenCx<'_, '_>,
|
cx: &CodegenCx<'_, '_>,
|
||||||
|
covfun_section_name: &str,
|
||||||
mangled_function_name: &str,
|
mangled_function_name: &str,
|
||||||
source_hash: u64,
|
source_hash: u64,
|
||||||
filenames_ref: u64,
|
filenames_ref: u64,
|
||||||
|
@ -254,7 +257,13 @@ fn save_function_record(
|
||||||
/*packed=*/ true,
|
/*packed=*/ true,
|
||||||
);
|
);
|
||||||
|
|
||||||
coverageinfo::save_func_record_to_mod(cx, func_name_hash, func_record_val, is_used);
|
coverageinfo::save_func_record_to_mod(
|
||||||
|
cx,
|
||||||
|
covfun_section_name,
|
||||||
|
func_name_hash,
|
||||||
|
func_record_val,
|
||||||
|
is_used,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// When finalizing the coverage map, `FunctionCoverage` only has the `CodeRegion`s and counters for
|
/// When finalizing the coverage map, `FunctionCoverage` only has the `CodeRegion`s and counters for
|
||||||
|
|
|
@ -408,6 +408,7 @@ pub(crate) fn save_cov_data_to_mod<'ll, 'tcx>(
|
||||||
|
|
||||||
pub(crate) fn save_func_record_to_mod<'ll, 'tcx>(
|
pub(crate) fn save_func_record_to_mod<'ll, 'tcx>(
|
||||||
cx: &CodegenCx<'ll, 'tcx>,
|
cx: &CodegenCx<'ll, 'tcx>,
|
||||||
|
covfun_section_name: &str,
|
||||||
func_name_hash: u64,
|
func_name_hash: u64,
|
||||||
func_record_val: &'ll llvm::Value,
|
func_record_val: &'ll llvm::Value,
|
||||||
is_used: bool,
|
is_used: bool,
|
||||||
|
@ -423,20 +424,33 @@ pub(crate) fn save_func_record_to_mod<'ll, 'tcx>(
|
||||||
let func_record_var_name =
|
let func_record_var_name =
|
||||||
format!("__covrec_{:X}{}", func_name_hash, if is_used { "u" } else { "" });
|
format!("__covrec_{:X}{}", func_name_hash, if is_used { "u" } else { "" });
|
||||||
debug!("function record var name: {:?}", func_record_var_name);
|
debug!("function record var name: {:?}", func_record_var_name);
|
||||||
|
debug!("function record section name: {:?}", covfun_section_name);
|
||||||
let func_record_section_name = llvm::build_string(|s| unsafe {
|
|
||||||
llvm::LLVMRustCoverageWriteFuncSectionNameToString(cx.llmod, s);
|
|
||||||
})
|
|
||||||
.expect("Rust Coverage function record section name failed UTF-8 conversion");
|
|
||||||
debug!("function record section name: {:?}", func_record_section_name);
|
|
||||||
|
|
||||||
let llglobal = llvm::add_global(cx.llmod, cx.val_ty(func_record_val), &func_record_var_name);
|
let llglobal = llvm::add_global(cx.llmod, cx.val_ty(func_record_val), &func_record_var_name);
|
||||||
llvm::set_initializer(llglobal, func_record_val);
|
llvm::set_initializer(llglobal, func_record_val);
|
||||||
llvm::set_global_constant(llglobal, true);
|
llvm::set_global_constant(llglobal, true);
|
||||||
llvm::set_linkage(llglobal, llvm::Linkage::LinkOnceODRLinkage);
|
llvm::set_linkage(llglobal, llvm::Linkage::LinkOnceODRLinkage);
|
||||||
llvm::set_visibility(llglobal, llvm::Visibility::Hidden);
|
llvm::set_visibility(llglobal, llvm::Visibility::Hidden);
|
||||||
llvm::set_section(llglobal, &func_record_section_name);
|
llvm::set_section(llglobal, covfun_section_name);
|
||||||
llvm::set_alignment(llglobal, VAR_ALIGN_BYTES);
|
llvm::set_alignment(llglobal, VAR_ALIGN_BYTES);
|
||||||
llvm::set_comdat(cx.llmod, llglobal, &func_record_var_name);
|
llvm::set_comdat(cx.llmod, llglobal, &func_record_var_name);
|
||||||
cx.add_used_global(llglobal);
|
cx.add_used_global(llglobal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the section name string to pass through to the linker when embedding
|
||||||
|
/// per-function coverage information in the object file, according to the target
|
||||||
|
/// platform's object file format.
|
||||||
|
///
|
||||||
|
/// LLVM's coverage tools read coverage mapping details from this section when
|
||||||
|
/// producing coverage reports.
|
||||||
|
///
|
||||||
|
/// Typical values are:
|
||||||
|
/// - `__llvm_covfun` on Linux
|
||||||
|
/// - `__LLVM_COV,__llvm_covfun` on macOS (includes `__LLVM_COV,` segment prefix)
|
||||||
|
/// - `.lcovfun$M` on Windows (includes `$M` sorting suffix)
|
||||||
|
pub(crate) fn covfun_section_name(cx: &CodegenCx<'_, '_>) -> String {
|
||||||
|
llvm::build_string(|s| unsafe {
|
||||||
|
llvm::LLVMRustCoverageWriteFuncSectionNameToString(cx.llmod, s);
|
||||||
|
})
|
||||||
|
.expect("Rust Coverage function record section name failed UTF-8 conversion")
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue