@@ -319,7 +319,64 @@ fn add_unused_functions<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) {
319319 continue ;
320320 }
321321
322- debug ! ( "generating unused fn: {:?}" , non_codegenned_def_id) ;
323- cx. define_unused_fn ( non_codegenned_def_id) ;
322+ if unused_def_ids_by_file. is_empty ( ) {
323+ // There are no unused functions with file names to add (in any CGU)
324+ return ;
325+ }
326+
327+ // Each `CodegenUnit` (CGU) has its own function_coverage_map, and generates a specific binary
328+ // with its own coverage map.
329+ //
330+ // Each covered function `Instance` can be included in only one coverage map, produced from a
331+ // specific function_coverage_map, from a specific CGU.
332+ //
333+ // Since unused functions did not generate code, they are not associated with any CGU yet.
334+ //
335+ // To avoid injecting the unused functions in multiple coverage maps (for multiple CGUs)
336+ // determine which function_coverage_map has the responsibility for publishing unreachable
337+ // coverage, based on file name: For each unused function, find the CGU that generates the
338+ // first function (based on sorted `DefId`) from the same file.
339+ //
340+ // Add a new `FunctionCoverage` to the `function_coverage_map`, with unreachable code regions
341+ // for each region in it's MIR.
342+
343+ let mut first_covered_def_id_by_file: FxHashMap < Symbol , DefId > = FxHashMap :: default ( ) ;
344+ for & def_id in codegenned_def_ids. iter ( ) {
345+ if let Some ( covered_file_name) = tcx. covered_file_name ( def_id) {
346+ // Only add files known to have unused functions
347+ if unused_def_ids_by_file. contains_key ( covered_file_name) {
348+ first_covered_def_id_by_file. entry ( * covered_file_name) . or_insert ( def_id) ;
349+ }
350+ }
351+ }
352+
353+ // Get the set of def_ids with coverage regions, known by *this* CoverageContext.
354+ let cgu_covered_def_ids: DefIdSet = match cx. coverage_context ( ) {
355+ Some ( ctx) => ctx
356+ . function_coverage_map
357+ . borrow ( )
358+ . keys ( )
359+ . map ( |& instance| instance. def . def_id ( ) )
360+ . collect ( ) ,
361+ None => return ,
362+ } ;
363+
364+ let cgu_covered_files: FxHashSet < Symbol > =
365+ first_covered_def_id_by_file
366+ . iter ( )
367+ . filter_map ( |( & file_name, def_id) | {
368+ if cgu_covered_def_ids. contains ( def_id) { Some ( file_name) } else { None }
369+ } )
370+ . collect ( ) ;
371+
372+ // For each file for which this CGU is responsible for adding unused function coverage,
373+ // get the `def_id`s for each unused function (if any), define a synthetic function with a
374+ // single LLVM coverage counter, and add the function's coverage `CodeRegion`s. to the
375+ // function_coverage_map.
376+ for covered_file_name in cgu_covered_files {
377+ for def_id in unused_def_ids_by_file. remove ( & covered_file_name) . into_iter ( ) . flatten ( ) {
378+ cx. define_unused_fn ( def_id) ;
379+ }
380+ }
324381 }
325382}
0 commit comments