1- mod  spans; 
2- 
31use  std:: ffi:: CString ; 
4- use  std:: sync :: Arc ; 
2+ use  std:: iter ; 
53
64use  itertools:: Itertools  as  _; 
75use  rustc_abi:: Align ; 
86use  rustc_codegen_ssa:: traits:: { 
97    BaseTypeCodegenMethods ,  ConstCodegenMethods ,  StaticCodegenMethods , 
108} ; 
11- use  rustc_data_structures:: fx:: { FxHashSet ,  FxIndexMap } ; 
9+ use  rustc_data_structures:: fx:: { FxHashSet ,  FxIndexMap ,   FxIndexSet } ; 
1210use  rustc_hir:: def_id:: { DefId ,  LocalDefId } ; 
1311use  rustc_index:: IndexVec ; 
1412use  rustc_middle:: mir:: coverage:: MappingKind ; 
@@ -17,7 +15,7 @@ use rustc_middle::{bug, mir};
1715use  rustc_session:: RemapFileNameExt ; 
1816use  rustc_session:: config:: RemapPathScopeComponents ; 
1917use  rustc_span:: def_id:: DefIdSet ; 
20- use  rustc_span:: { SourceFile ,   StableSourceFileId } ; 
18+ use  rustc_span:: { Span ,   Symbol } ; 
2119use  rustc_target:: spec:: HasTargetSpec ; 
2220use  tracing:: debug; 
2321
@@ -74,11 +72,11 @@ pub(crate) fn finalize(cx: &CodegenCx<'_, '_>) {
7472        . map ( |( instance,  function_coverage) | ( instance,  function_coverage. into_finished ( ) ) ) 
7573        . collect :: < Vec < _ > > ( ) ; 
7674
77-     let  all_files  = function_coverage_entries
75+     let  all_file_names  = function_coverage_entries
7876        . iter ( ) 
7977        . map ( |( _,  fn_cov) | fn_cov. function_coverage_info . body_span ) 
80-         . map ( |span| tcx . sess . source_map ( ) . lookup_source_file ( span. lo ( ) ) ) ; 
81-     let  global_file_table = GlobalFileTable :: new ( all_files ) ; 
78+         . map ( |span| span_file_name ( tcx ,   span) ) ; 
79+     let  global_file_table = GlobalFileTable :: new ( all_file_names ) ; 
8280
8381    // Encode all filenames referenced by coverage mappings in this CGU. 
8482    let  filenames_buffer = global_file_table. make_filenames_buffer ( tcx) ; 
@@ -105,8 +103,15 @@ pub(crate) fn finalize(cx: &CodegenCx<'_, '_>) {
105103            encode_mappings_for_function ( tcx,  & global_file_table,  & function_coverage) ; 
106104
107105        if  coverage_mapping_buffer. is_empty ( )  { 
108-             debug ! ( "function has no mappings to embed; skipping" ) ; 
109-             continue ; 
106+             if  function_coverage. is_used ( )  { 
107+                 bug ! ( 
108+                     "A used function should have had coverage mapping data but did not: {}" , 
109+                     mangled_function_name
110+                 ) ; 
111+             }  else  { 
112+                 debug ! ( "unused function had no coverage mapping data: {}" ,  mangled_function_name) ; 
113+                 continue ; 
114+             } 
110115        } 
111116
112117        if  !is_used { 
@@ -143,62 +148,54 @@ pub(crate) fn finalize(cx: &CodegenCx<'_, '_>) {
143148    } 
144149} 
145150
146- /// Maps "global" (per-CGU) file ID numbers to their underlying source files . 
151+ /// Maps "global" (per-CGU) file ID numbers to their underlying filenames . 
147152struct  GlobalFileTable  { 
148-     /// This "raw" table doesn't include the working dir, so a file 's 
153+     /// This "raw" table doesn't include the working dir, so a filename 's 
149154/// global ID is its index in this set **plus one**. 
150- raw_file_table :  FxIndexMap < StableSourceFileId ,   Arc < SourceFile > > , 
155+ raw_file_table :  FxIndexSet < Symbol > , 
151156} 
152157
153158impl  GlobalFileTable  { 
154-     fn  new ( all_files :  impl  IntoIterator < Item  = Arc < SourceFile > > )  -> Self  { 
155-         // Collect all of the files into a set. Files usually come in contiguous 
156-         // runs, so we can dedup adjacent ones to save work. 
157-         let  mut  raw_file_table = all_files
158-             . into_iter ( ) 
159-             . dedup_by ( |a,  b| a. stable_id  == b. stable_id ) 
160-             . map ( |f| ( f. stable_id ,  f) ) 
161-             . collect :: < FxIndexMap < StableSourceFileId ,  Arc < SourceFile > > > ( ) ; 
159+     fn  new ( all_file_names :  impl  IntoIterator < Item  = Symbol > )  -> Self  { 
160+         // Collect all of the filenames into a set. Filenames usually come in 
161+         // contiguous runs, so we can dedup adjacent ones to save work. 
162+         let  mut  raw_file_table = all_file_names. into_iter ( ) . dedup ( ) . collect :: < FxIndexSet < Symbol > > ( ) ; 
162163
163-         // Sort the file table by its underlying filenames. 
164-         raw_file_table. sort_unstable_by ( |_,  a,  _,  b| { 
165-             Ord :: cmp ( & a. name ,  & b. name ) . then_with ( || Ord :: cmp ( & a. stable_id ,  & b. stable_id ) ) 
166-         } ) ; 
164+         // Sort the file table by its actual string values, not the arbitrary 
165+         // ordering of its symbols. 
166+         raw_file_table. sort_unstable_by ( |a,  b| a. as_str ( ) . cmp ( b. as_str ( ) ) ) ; 
167167
168168        Self  {  raw_file_table } 
169169    } 
170170
171-     fn  global_file_id_for_file ( & self ,  file :   & SourceFile )  -> GlobalFileId  { 
172-         let  raw_id = self . raw_file_table . get_index_of ( & file . stable_id ) . unwrap_or_else ( || { 
173-             bug ! ( "file not found in prepared global file table: {:?}"  ,  file . name ) ; 
171+     fn  global_file_id_for_file_name ( & self ,  file_name :   Symbol )  -> GlobalFileId  { 
172+         let  raw_id = self . raw_file_table . get_index_of ( & file_name ) . unwrap_or_else ( || { 
173+             bug ! ( "file name  not found in prepared global file table: {file_name}"  ) ; 
174174        } ) ; 
175175        // The raw file table doesn't include an entry for the working dir 
176176        // (which has ID 0), so add 1 to get the correct ID. 
177177        GlobalFileId :: from_usize ( raw_id + 1 ) 
178178    } 
179179
180180    fn  make_filenames_buffer ( & self ,  tcx :  TyCtxt < ' _ > )  -> Vec < u8 >  { 
181-         let  mut  table = Vec :: with_capacity ( self . raw_file_table . len ( )  + 1 ) ; 
182- 
183181        // LLVM Coverage Mapping Format version 6 (zero-based encoded as 5) 
184182        // requires setting the first filename to the compilation directory. 
185183        // Since rustc generates coverage maps with relative paths, the 
186184        // compilation directory can be combined with the relative paths 
187185        // to get absolute paths, if needed. 
188-         table. push ( 
189-             tcx. sess 
190-                 . opts 
191-                 . working_dir 
192-                 . for_scope ( tcx. sess ,  RemapPathScopeComponents :: MACRO ) 
193-                 . to_string_lossy ( ) , 
194-         ) ; 
195- 
196-         // Add the regular entries after the base directory. 
197-         table. extend ( self . raw_file_table . values ( ) . map ( |file| { 
198-             file. name . for_scope ( tcx. sess ,  RemapPathScopeComponents :: MACRO ) . to_string_lossy ( ) 
199-         } ) ) ; 
200- 
201-         llvm_cov:: write_filenames_to_buffer ( table. iter ( ) . map ( |f| f. as_ref ( ) ) ) 
186+         use  rustc_session:: RemapFileNameExt ; 
187+         use  rustc_session:: config:: RemapPathScopeComponents ; 
188+         let  working_dir:  & str  = & tcx
189+             . sess 
190+             . opts 
191+             . working_dir 
192+             . for_scope ( tcx. sess ,  RemapPathScopeComponents :: MACRO ) 
193+             . to_string_lossy ( ) ; 
194+ 
195+         // Insert the working dir at index 0, before the other filenames. 
196+         let  filenames =
197+             iter:: once ( working_dir) . chain ( self . raw_file_table . iter ( ) . map ( Symbol :: as_str) ) ; 
198+         llvm_cov:: write_filenames_to_buffer ( filenames) 
202199    } 
203200} 
204201
@@ -211,7 +208,7 @@ rustc_index::newtype_index! {
211208    /// An index into a function's list of global file IDs. That underlying list 
212209/// of local-to-global mappings will be embedded in the function's record in 
213210/// the `__llvm_covfun` linker section. 
214- struct  LocalFileId  { } 
211+ pub ( crate )   struct  LocalFileId  { } 
215212} 
216213
217214/// Holds a mapping from "local" (per-function) file IDs to "global" (per-CGU) 
@@ -237,6 +234,13 @@ impl VirtualFileMapping {
237234    } 
238235} 
239236
237+ fn  span_file_name ( tcx :  TyCtxt < ' _ > ,  span :  Span )  -> Symbol  { 
238+     let  source_file = tcx. sess . source_map ( ) . lookup_source_file ( span. lo ( ) ) ; 
239+     let  name =
240+         source_file. name . for_scope ( tcx. sess ,  RemapPathScopeComponents :: MACRO ) . to_string_lossy ( ) ; 
241+     Symbol :: intern ( & name) 
242+ } 
243+ 
240244/// Using the expressions and counter regions collected for a single function, 
241245/// generate the variable-sized payload of its corresponding `__llvm_covfun` 
242246/// entry. The payload is returned as a vector of bytes. 
@@ -247,13 +251,11 @@ fn encode_mappings_for_function(
247251    global_file_table :  & GlobalFileTable , 
248252    function_coverage :  & FunctionCoverage < ' _ > , 
249253)  -> Vec < u8 >  { 
250-     let  mapping_spans  = function_coverage. mapping_spans ( ) ; 
251-     if  mapping_spans . is_empty ( )  { 
254+     let  counter_regions  = function_coverage. counter_regions ( ) ; 
255+     if  counter_regions . is_empty ( )  { 
252256        return  Vec :: new ( ) ; 
253257    } 
254258
255-     let  fn_cov_info = function_coverage. function_coverage_info ; 
256- 
257259    let  expressions = function_coverage. counter_expressions ( ) . collect :: < Vec < _ > > ( ) ; 
258260
259261    let  mut  virtual_file_mapping = VirtualFileMapping :: default ( ) ; 
@@ -263,47 +265,42 @@ fn encode_mappings_for_function(
263265    let  mut  mcdc_decision_regions = vec ! [ ] ; 
264266
265267    // Currently a function's mappings must all be in the same file as its body span. 
266-     let  source_map = tcx. sess . source_map ( ) ; 
267-     let  source_file = source_map. lookup_source_file ( fn_cov_info. body_span . lo ( ) ) ; 
268+     let  file_name = span_file_name ( tcx,  function_coverage. function_coverage_info . body_span ) ; 
268269
269-     // Look up the global file ID for that file . 
270-     let  global_file_id = global_file_table. global_file_id_for_file ( & source_file ) ; 
270+     // Look up the global file ID for that filename . 
271+     let  global_file_id = global_file_table. global_file_id_for_file_name ( file_name ) ; 
271272
272273    // Associate that global file ID with a local file ID for this function. 
273274    let  local_file_id = virtual_file_mapping. local_id_for_global ( global_file_id) ; 
275+     debug ! ( "  file id: {local_file_id:?} => {global_file_id:?} = '{file_name:?}'" ) ; 
274276
275-     let  make_cov_span = |span| { 
276-         spans:: make_coverage_span ( local_file_id,  source_map,  fn_cov_info,  & source_file,  span) 
277-     } ; 
278- 
279-     // For each coverage mapping span in this function+file, convert it to a 
277+     // For each counter/region pair in this function+file, convert it to a 
280278    // form suitable for FFI. 
281-     for  ( mapping_kind,  span )  in  mapping_spans  { 
282-         debug ! ( "Adding counter {mapping_kind:?} to map for {span :?}" ) ; 
283-         let  Some ( cov_span )  = make_cov_span ( span )   else   {   continue   } ; 
279+     for  ( mapping_kind,  region )  in  counter_regions  { 
280+         debug ! ( "Adding counter {mapping_kind:?} to map for {region :?}" ) ; 
281+         let  span  = ffi :: CoverageSpan :: from_source_region ( local_file_id ,  region ) ; 
284282        match  mapping_kind { 
285283            MappingKind :: Code ( term)  => { 
286-                 code_regions
287-                     . push ( ffi:: CodeRegion  {  cov_span,  counter :  ffi:: Counter :: from_term ( term)  } ) ; 
284+                 code_regions. push ( ffi:: CodeRegion  {  span,  counter :  ffi:: Counter :: from_term ( term)  } ) ; 
288285            } 
289286            MappingKind :: Branch  {  true_term,  false_term }  => { 
290287                branch_regions. push ( ffi:: BranchRegion  { 
291-                     cov_span , 
288+                     span , 
292289                    true_counter :  ffi:: Counter :: from_term ( true_term) , 
293290                    false_counter :  ffi:: Counter :: from_term ( false_term) , 
294291                } ) ; 
295292            } 
296293            MappingKind :: MCDCBranch  {  true_term,  false_term,  mcdc_params }  => { 
297294                mcdc_branch_regions. push ( ffi:: MCDCBranchRegion  { 
298-                     cov_span , 
295+                     span , 
299296                    true_counter :  ffi:: Counter :: from_term ( true_term) , 
300297                    false_counter :  ffi:: Counter :: from_term ( false_term) , 
301298                    mcdc_branch_params :  ffi:: mcdc:: BranchParameters :: from ( mcdc_params) , 
302299                } ) ; 
303300            } 
304301            MappingKind :: MCDCDecision ( mcdc_decision_params)  => { 
305302                mcdc_decision_regions. push ( ffi:: MCDCDecisionRegion  { 
306-                     cov_span , 
303+                     span , 
307304                    mcdc_decision_params :  ffi:: mcdc:: DecisionParameters :: from ( mcdc_decision_params) , 
308305                } ) ; 
309306            } 
0 commit comments