@@ -319,7 +319,64 @@ fn add_unused_functions<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) {
319
319
continue ;
320
320
}
321
321
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
+ }
324
381
}
325
382
}
0 commit comments