@@ -11,7 +11,9 @@ use rustc_codegen_ssa::traits::{
1111 BaseTypeCodegenMethods , ConstCodegenMethods , StaticCodegenMethods ,
1212} ;
1313use rustc_middle:: bug;
14- use rustc_middle:: mir:: coverage:: MappingKind ;
14+ use rustc_middle:: mir:: coverage:: {
15+ CoverageIdsInfo , Expression , FunctionCoverageInfo , MappingKind , Op ,
16+ } ;
1517use rustc_middle:: ty:: { Instance , TyCtxt } ;
1618use rustc_target:: spec:: HasTargetSpec ;
1719use tracing:: debug;
@@ -49,12 +51,17 @@ pub(crate) fn prepare_covfun_record<'tcx>(
4951 instance : Instance < ' tcx > ,
5052 function_coverage : & FunctionCoverage < ' tcx > ,
5153) -> Option < CovfunRecord < ' tcx > > {
54+ let fn_cov_info = tcx. instance_mir ( instance. def ) . function_coverage_info . as_deref ( ) ?;
55+ let ids_info = tcx. coverage_ids_info ( instance. def ) ;
56+
57+ let expressions = prepare_expressions ( fn_cov_info, ids_info, function_coverage. is_used ( ) ) ;
58+
5259 let mut covfun = CovfunRecord {
5360 mangled_function_name : tcx. symbol_name ( instance) . name ,
5461 source_hash : function_coverage. source_hash ( ) ,
5562 is_used : function_coverage. is_used ( ) ,
5663 virtual_file_mapping : VirtualFileMapping :: default ( ) ,
57- expressions : function_coverage . counter_expressions ( ) . collect :: < Vec < _ > > ( ) ,
64+ expressions,
5865 regions : ffi:: Regions :: default ( ) ,
5966 } ;
6067
@@ -72,6 +79,40 @@ pub(crate) fn prepare_covfun_record<'tcx>(
7279 Some ( covfun)
7380}
7481
82+ /// Convert the function's coverage-counter expressions into a form suitable for FFI.
83+ fn prepare_expressions (
84+ fn_cov_info : & FunctionCoverageInfo ,
85+ ids_info : & CoverageIdsInfo ,
86+ is_used : bool ,
87+ ) -> Vec < ffi:: CounterExpression > {
88+ // If any counters or expressions were removed by MIR opts, replace their
89+ // terms with zero.
90+ let counter_for_term = |term| {
91+ if !is_used || ids_info. is_zero_term ( term) {
92+ ffi:: Counter :: ZERO
93+ } else {
94+ ffi:: Counter :: from_term ( term)
95+ }
96+ } ;
97+
98+ // We know that LLVM will optimize out any unused expressions before
99+ // producing the final coverage map, so there's no need to do the same
100+ // thing on the Rust side unless we're confident we can do much better.
101+ // (See `CounterExpressionsMinimizer` in `CoverageMappingWriter.cpp`.)
102+ fn_cov_info
103+ . expressions
104+ . iter ( )
105+ . map ( move |& Expression { lhs, op, rhs } | ffi:: CounterExpression {
106+ lhs : counter_for_term ( lhs) ,
107+ kind : match op {
108+ Op :: Add => ffi:: ExprKind :: Add ,
109+ Op :: Subtract => ffi:: ExprKind :: Subtract ,
110+ } ,
111+ rhs : counter_for_term ( rhs) ,
112+ } )
113+ . collect :: < Vec < _ > > ( )
114+ }
115+
75116/// Populates the mapping region tables in the current function's covfun record.
76117fn fill_region_tables < ' tcx > (
77118 tcx : TyCtxt < ' tcx > ,
0 commit comments