@@ -75,10 +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-
79- let filenames_size = filenames_buffer . len ( ) ;
80- let filenames_val = cx . const_bytes ( & filenames_buffer ) ;
81- 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) ;
8282
8383 let mut unused_function_names = Vec :: new ( ) ;
8484
@@ -101,7 +101,7 @@ pub(crate) fn finalize(cx: &CodegenCx<'_, '_>) {
101101 for covfun in & covfun_records {
102102 unused_function_names. extend ( covfun. mangled_function_name_if_unused ( ) ) ;
103103
104- covfun:: generate_covfun_record ( cx, filenames_ref , covfun)
104+ covfun:: generate_covfun_record ( cx, filenames_hash , covfun)
105105 }
106106
107107 // For unused functions, we need to take their mangled names and store them
@@ -126,7 +126,7 @@ pub(crate) fn finalize(cx: &CodegenCx<'_, '_>) {
126126 // Generate the coverage map header, which contains the filenames used by
127127 // this CGU's coverage mappings, and store it in a well-known global.
128128 // (This is skipped if we returned early due to having no covfun records.)
129- generate_covmap_record ( cx, covmap_version, filenames_size , filenames_val ) ;
129+ generate_covmap_record ( cx, covmap_version, & filenames_buffer ) ;
130130}
131131
132132/// Maps "global" (per-CGU) file ID numbers to their underlying filenames.
@@ -225,38 +225,35 @@ fn span_file_name(tcx: TyCtxt<'_>, span: Span) -> Symbol {
225225/// Generates the contents of the covmap record for this CGU, which mostly
226226/// consists of a header and a list of filenames. The record is then stored
227227/// as a global variable in the `__llvm_covmap` section.
228- fn generate_covmap_record < ' ll > (
229- cx : & CodegenCx < ' ll , ' _ > ,
230- version : u32 ,
231- filenames_size : usize ,
232- filenames_val : & ' ll llvm:: Value ,
233- ) {
234- debug ! ( "cov map: filenames_size = {}, 0-based version = {}" , filenames_size, version) ;
235-
236- // Create the coverage data header (Note, fields 0 and 2 are now always zero,
237- // as of `llvm::coverage::CovMapVersion::Version4`.)
238- let zero_was_n_records_val = cx. const_u32 ( 0 ) ;
239- let filenames_size_val = cx. const_u32 ( filenames_size as u32 ) ;
240- let zero_was_coverage_size_val = cx. const_u32 ( 0 ) ;
241- let version_val = cx. const_u32 ( version) ;
242- let cov_data_header_val = cx. const_struct (
243- & [ zero_was_n_records_val, filenames_size_val, zero_was_coverage_size_val, version_val] ,
244- /*packed=*/ false ,
228+ fn generate_covmap_record < ' ll > ( cx : & CodegenCx < ' ll , ' _ > , version : u32 , filenames_buffer : & [ u8 ] ) {
229+ // A covmap record consists of four target-endian u32 values, followed by
230+ // the encoded filenames table. Two of the header fields are unused in
231+ // modern versions of the LLVM coverage mapping format, and are always 0.
232+ // <https://llvm.org/docs/CoverageMappingFormat.html#llvm-ir-representation>
233+ // See also `src/llvm-project/clang/lib/CodeGen/CoverageMappingGen.cpp`.
234+ let covmap_header = cx. const_struct (
235+ & [
236+ cx. const_u32 ( 0 ) , // (unused)
237+ cx. const_u32 ( filenames_buffer. len ( ) as u32 ) ,
238+ cx. const_u32 ( 0 ) , // (unused)
239+ cx. const_u32 ( version) ,
240+ ] ,
241+ /* packed */ false ,
245242 ) ;
246-
247- // Create the complete LLVM coverage data value to add to the LLVM IR
248- let covmap_data =
249- cx. const_struct ( & [ cov_data_header_val, filenames_val] , /*packed=*/ false ) ;
250-
251- let llglobal = llvm:: add_global ( cx. llmod , cx. val_ty ( covmap_data) , & llvm_cov:: covmap_var_name ( ) ) ;
252- llvm:: set_initializer ( llglobal, covmap_data) ;
253- llvm:: set_global_constant ( llglobal, true ) ;
254- llvm:: set_linkage ( llglobal, llvm:: Linkage :: PrivateLinkage ) ;
255- llvm:: set_section ( llglobal, & llvm_cov:: covmap_section_name ( cx. llmod ) ) ;
243+ let covmap_record = cx
244+ . const_struct ( & [ covmap_header, cx. const_bytes ( filenames_buffer) ] , /* packed */ false ) ;
245+
246+ let covmap_global =
247+ llvm:: add_global ( cx. llmod , cx. val_ty ( covmap_record) , & llvm_cov:: covmap_var_name ( ) ) ;
248+ llvm:: set_initializer ( covmap_global, covmap_record) ;
249+ llvm:: set_global_constant ( covmap_global, true ) ;
250+ llvm:: set_linkage ( covmap_global, llvm:: Linkage :: PrivateLinkage ) ;
251+ llvm:: set_section ( covmap_global, & llvm_cov:: covmap_section_name ( cx. llmod ) ) ;
256252 // LLVM's coverage mapping format specifies 8-byte alignment for items in this section.
257253 // <https://llvm.org/docs/CoverageMappingFormat.html>
258- llvm:: set_alignment ( llglobal, Align :: EIGHT ) ;
259- cx. add_used_global ( llglobal) ;
254+ llvm:: set_alignment ( covmap_global, Align :: EIGHT ) ;
255+
256+ cx. add_used_global ( covmap_global) ;
260257}
261258
262259/// Each CGU will normally only emit coverage metadata for the functions that it actually generates.
0 commit comments