From 01f3cc127227e607c2699fcd5fb2d17f1217a0cd Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 24 Jul 2023 21:15:11 +1000 Subject: [PATCH] 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. --- .../src/coverageinfo/mapgen.rs | 11 +++++++- .../src/coverageinfo/mod.rs | 28 ++++++++++++++----- 2 files changed, 31 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs index 6e815ab3ff5..9149b06886b 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs @@ -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 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 { save_function_record( cx, + &covfun_section_name, mangled_function_name, source_hash, filenames_ref, @@ -228,6 +230,7 @@ fn generate_coverage_map<'ll>( /// specific, well-known section and name. fn save_function_record( cx: &CodegenCx<'_, '_>, + covfun_section_name: &str, mangled_function_name: &str, source_hash: u64, filenames_ref: u64, @@ -254,7 +257,13 @@ fn save_function_record( /*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 diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs index 1f8f4033931..60cbb3d3d9d 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs @@ -408,6 +408,7 @@ pub(crate) fn save_cov_data_to_mod<'ll, 'tcx>( pub(crate) fn save_func_record_to_mod<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, + covfun_section_name: &str, func_name_hash: u64, func_record_val: &'ll llvm::Value, is_used: bool, @@ -423,20 +424,33 @@ pub(crate) fn save_func_record_to_mod<'ll, 'tcx>( let func_record_var_name = format!("__covrec_{:X}{}", func_name_hash, if is_used { "u" } else { "" }); debug!("function record var name: {:?}", func_record_var_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); + debug!("function record section name: {:?}", covfun_section_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_global_constant(llglobal, true); llvm::set_linkage(llglobal, llvm::Linkage::LinkOnceODRLinkage); 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_comdat(cx.llmod, llglobal, &func_record_var_name); 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") +}