1- use std:: ffi:: CStr ;
1+ use std:: ffi:: { CStr , CString } ;
22
33use itertools:: Itertools as _;
4- use rustc_codegen_ssa:: traits:: { BaseTypeCodegenMethods , ConstCodegenMethods } ;
4+ use rustc_abi:: Align ;
5+ use rustc_codegen_ssa:: traits:: {
6+ BaseTypeCodegenMethods , ConstCodegenMethods , StaticCodegenMethods ,
7+ } ;
58use rustc_data_structures:: fx:: { FxHashSet , FxIndexMap , FxIndexSet } ;
69use rustc_hir:: def_id:: { DefId , LocalDefId } ;
710use rustc_index:: IndexVec ;
@@ -10,6 +13,7 @@ use rustc_middle::ty::{self, TyCtxt};
1013use rustc_middle:: { bug, mir} ;
1114use rustc_span:: Symbol ;
1215use rustc_span:: def_id:: DefIdSet ;
16+ use rustc_target:: spec:: HasTargetSpec ;
1317use tracing:: debug;
1418
1519use crate :: common:: CodegenCx ;
@@ -78,8 +82,7 @@ pub(crate) fn finalize(cx: &CodegenCx<'_, '_>) {
7882
7983 // Generate the coverage map header, which contains the filenames used by
8084 // this CGU's coverage mappings, and store it in a well-known global.
81- let cov_data_val = generate_coverage_map ( cx, covmap_version, filenames_size, filenames_val) ;
82- coverageinfo:: save_cov_data_to_mod ( cx, cov_data_val) ;
85+ generate_covmap_record ( cx, covmap_version, filenames_size, filenames_val) ;
8386
8487 let mut unused_function_names = Vec :: new ( ) ;
8588 let covfun_section_name = coverageinfo:: covfun_section_name ( cx) ;
@@ -111,7 +114,7 @@ pub(crate) fn finalize(cx: &CodegenCx<'_, '_>) {
111114 unused_function_names. push ( mangled_function_name) ;
112115 }
113116
114- save_function_record (
117+ generate_covfun_record (
115118 cx,
116119 & covfun_section_name,
117120 mangled_function_name,
@@ -308,15 +311,15 @@ fn encode_mappings_for_function(
308311 } )
309312}
310313
311- /// Construct coverage map header and the array of function records, and combine them into the
312- /// coverage map. Save the coverage map data into the LLVM IR as a static global using a
313- /// specific, well-known section and name .
314- fn generate_coverage_map < ' ll > (
314+ /// Generates the contents of the covmap record for this CGU, which mostly
315+ /// consists of a header and a list of filenames. The record is then stored
316+ /// as a global variable in the `__llvm_covmap` section .
317+ fn generate_covmap_record < ' ll > (
315318 cx : & CodegenCx < ' ll , ' _ > ,
316319 version : u32 ,
317320 filenames_size : usize ,
318321 filenames_val : & ' ll llvm:: Value ,
319- ) -> & ' ll llvm :: Value {
322+ ) {
320323 debug ! ( "cov map: filenames_size = {}, 0-based version = {}" , filenames_size, version) ;
321324
322325 // Create the coverage data header (Note, fields 0 and 2 are now always zero,
@@ -331,13 +334,35 @@ fn generate_coverage_map<'ll>(
331334 ) ;
332335
333336 // Create the complete LLVM coverage data value to add to the LLVM IR
334- cx. const_struct ( & [ cov_data_header_val, filenames_val] , /*packed=*/ false )
337+ let covmap_data =
338+ cx. const_struct ( & [ cov_data_header_val, filenames_val] , /*packed=*/ false ) ;
339+
340+ let covmap_var_name = CString :: new ( llvm:: build_byte_buffer ( |s| unsafe {
341+ llvm:: LLVMRustCoverageWriteMappingVarNameToString ( s) ;
342+ } ) )
343+ . unwrap ( ) ;
344+ debug ! ( "covmap var name: {:?}" , covmap_var_name) ;
345+
346+ let covmap_section_name = CString :: new ( llvm:: build_byte_buffer ( |s| unsafe {
347+ llvm:: LLVMRustCoverageWriteMapSectionNameToString ( cx. llmod , s) ;
348+ } ) )
349+ . expect ( "covmap section name should not contain NUL" ) ;
350+ debug ! ( "covmap section name: {:?}" , covmap_section_name) ;
351+
352+ let llglobal = llvm:: add_global ( cx. llmod , cx. val_ty ( covmap_data) , & covmap_var_name) ;
353+ llvm:: set_initializer ( llglobal, covmap_data) ;
354+ llvm:: set_global_constant ( llglobal, true ) ;
355+ llvm:: set_linkage ( llglobal, llvm:: Linkage :: PrivateLinkage ) ;
356+ llvm:: set_section ( llglobal, & covmap_section_name) ;
357+ // LLVM's coverage mapping format specifies 8-byte alignment for items in this section.
358+ llvm:: set_alignment ( llglobal, Align :: EIGHT ) ;
359+ cx. add_used_global ( llglobal) ;
335360}
336361
337- /// Construct a function record and combine it with the function's coverage mapping data.
338- /// Save the function record into the LLVM IR as a static global using a
339- /// specific, well-known section and name .
340- fn save_function_record (
362+ /// Generates the contents of the covfun record for this function, which
363+ /// contains the function's coverage mapping data. The record is then stored
364+ /// as a global variable in the `__llvm_covfun` section .
365+ fn generate_covfun_record (
341366 cx : & CodegenCx < ' _ , ' _ > ,
342367 covfun_section_name : & CStr ,
343368 mangled_function_name : & str ,
@@ -366,13 +391,27 @@ fn save_function_record(
366391 /*packed=*/ true ,
367392 ) ;
368393
369- coverageinfo:: save_func_record_to_mod (
370- cx,
371- covfun_section_name,
372- func_name_hash,
373- func_record_val,
374- is_used,
375- ) ;
394+ // Choose a variable name to hold this function's covfun data.
395+ // Functions that are used have a suffix ("u") to distinguish them from
396+ // unused copies of the same function (from different CGUs), so that if a
397+ // linker sees both it won't discard the used copy's data.
398+ let func_record_var_name =
399+ CString :: new ( format ! ( "__covrec_{:X}{}" , func_name_hash, if is_used { "u" } else { "" } ) )
400+ . unwrap ( ) ;
401+ debug ! ( "function record var name: {:?}" , func_record_var_name) ;
402+
403+ let llglobal = llvm:: add_global ( cx. llmod , cx. val_ty ( func_record_val) , & func_record_var_name) ;
404+ llvm:: set_initializer ( llglobal, func_record_val) ;
405+ llvm:: set_global_constant ( llglobal, true ) ;
406+ llvm:: set_linkage ( llglobal, llvm:: Linkage :: LinkOnceODRLinkage ) ;
407+ llvm:: set_visibility ( llglobal, llvm:: Visibility :: Hidden ) ;
408+ llvm:: set_section ( llglobal, covfun_section_name) ;
409+ // LLVM's coverage mapping format specifies 8-byte alignment for items in this section.
410+ llvm:: set_alignment ( llglobal, Align :: EIGHT ) ;
411+ if cx. target_spec ( ) . supports_comdat ( ) {
412+ llvm:: set_comdat ( cx. llmod , llglobal, & func_record_var_name) ;
413+ }
414+ cx. add_used_global ( llglobal) ;
376415}
377416
378417/// Each CGU will normally only emit coverage metadata for the functions that it actually generates.
0 commit comments