11use rustc_data_structures:: captures:: Captures ;
22use rustc_data_structures:: fx:: FxIndexSet ;
33use rustc_index:: bit_set:: BitSet ;
4+ use rustc_middle:: mir:: CoverageIdsInfo ;
45use rustc_middle:: mir:: coverage:: {
56 CounterId , CovTerm , Expression , ExpressionId , FunctionCoverageInfo , Mapping , MappingKind , Op ,
67 SourceRegion ,
78} ;
89use rustc_middle:: ty:: Instance ;
9- use tracing:: { debug, instrument } ;
10+ use tracing:: debug;
1011
1112use crate :: coverageinfo:: ffi:: { Counter , CounterExpression , ExprKind } ;
1213
@@ -16,39 +17,33 @@ use crate::coverageinfo::ffi::{Counter, CounterExpression, ExprKind};
1617pub ( crate ) struct FunctionCoverageCollector < ' tcx > {
1718 /// Coverage info that was attached to this function by the instrumentor.
1819 function_coverage_info : & ' tcx FunctionCoverageInfo ,
20+ ids_info : & ' tcx CoverageIdsInfo ,
1921 is_used : bool ,
20-
21- /// Tracks which counters have been seen, so that we can identify mappings
22- /// to counters that were optimized out, and set them to zero.
23- counters_seen : BitSet < CounterId > ,
24- /// Contains all expression IDs that have been seen in an `ExpressionUsed`
25- /// coverage statement, plus all expression IDs that aren't directly used
26- /// by any mappings (and therefore do not have expression-used statements).
27- /// After MIR traversal is finished, we can conclude that any IDs missing
28- /// from this set must have had their statements deleted by MIR opts.
29- expressions_seen : BitSet < ExpressionId > ,
3022}
3123
3224impl < ' tcx > FunctionCoverageCollector < ' tcx > {
3325 /// Creates a new set of coverage data for a used (called) function.
3426 pub ( crate ) fn new (
3527 instance : Instance < ' tcx > ,
3628 function_coverage_info : & ' tcx FunctionCoverageInfo ,
29+ ids_info : & ' tcx CoverageIdsInfo ,
3730 ) -> Self {
38- Self :: create ( instance, function_coverage_info, true )
31+ Self :: create ( instance, function_coverage_info, ids_info , true )
3932 }
4033
4134 /// Creates a new set of coverage data for an unused (never called) function.
4235 pub ( crate ) fn unused (
4336 instance : Instance < ' tcx > ,
4437 function_coverage_info : & ' tcx FunctionCoverageInfo ,
38+ ids_info : & ' tcx CoverageIdsInfo ,
4539 ) -> Self {
46- Self :: create ( instance, function_coverage_info, false )
40+ Self :: create ( instance, function_coverage_info, ids_info , false )
4741 }
4842
4943 fn create (
5044 instance : Instance < ' tcx > ,
5145 function_coverage_info : & ' tcx FunctionCoverageInfo ,
46+ ids_info : & ' tcx CoverageIdsInfo ,
5247 is_used : bool ,
5348 ) -> Self {
5449 let num_counters = function_coverage_info. num_counters ;
@@ -58,44 +53,7 @@ impl<'tcx> FunctionCoverageCollector<'tcx> {
5853 num_counters={num_counters}, num_expressions={num_expressions}, is_used={is_used}"
5954 ) ;
6055
61- // Create a filled set of expression IDs, so that expressions not
62- // directly used by mappings will be treated as "seen".
63- // (If they end up being unused, LLVM will delete them for us.)
64- let mut expressions_seen = BitSet :: new_filled ( num_expressions) ;
65- // For each expression ID that is directly used by one or more mappings,
66- // mark it as not-yet-seen. This indicates that we expect to see a
67- // corresponding `ExpressionUsed` statement during MIR traversal.
68- for mapping in function_coverage_info. mappings . iter ( ) {
69- // Currently we only worry about ordinary code mappings.
70- // For branch and MC/DC mappings, expressions might not correspond
71- // to any particular point in the control-flow graph.
72- // (Keep this in sync with the injection of `ExpressionUsed`
73- // statements in the `InstrumentCoverage` MIR pass.)
74- if let MappingKind :: Code ( term) = mapping. kind
75- && let CovTerm :: Expression ( id) = term
76- {
77- expressions_seen. remove ( id) ;
78- }
79- }
80-
81- Self {
82- function_coverage_info,
83- is_used,
84- counters_seen : BitSet :: new_empty ( num_counters) ,
85- expressions_seen,
86- }
87- }
88-
89- /// Marks a counter ID as having been seen in a counter-increment statement.
90- #[ instrument( level = "debug" , skip( self ) ) ]
91- pub ( crate ) fn mark_counter_id_seen ( & mut self , id : CounterId ) {
92- self . counters_seen . insert ( id) ;
93- }
94-
95- /// Marks an expression ID as having been seen in an expression-used statement.
96- #[ instrument( level = "debug" , skip( self ) ) ]
97- pub ( crate ) fn mark_expression_id_seen ( & mut self , id : ExpressionId ) {
98- self . expressions_seen . insert ( id) ;
56+ Self { function_coverage_info, ids_info, is_used }
9957 }
10058
10159 /// Identify expressions that will always have a value of zero, and note
@@ -117,7 +75,7 @@ impl<'tcx> FunctionCoverageCollector<'tcx> {
11775 // (By construction, expressions can only refer to other expressions
11876 // that have lower IDs, so one pass is sufficient.)
11977 for ( id, expression) in self . function_coverage_info . expressions . iter_enumerated ( ) {
120- if !self . expressions_seen . contains ( id) {
78+ if !self . is_used || ! self . ids_info . expressions_seen . contains ( id) {
12179 // If an expression was not seen, it must have been optimized away,
12280 // so any operand that refers to it can be replaced with zero.
12381 zero_expressions. insert ( id) ;
@@ -146,7 +104,7 @@ impl<'tcx> FunctionCoverageCollector<'tcx> {
146104 assert_operand_expression_is_lower ( id) ;
147105 }
148106
149- if is_zero_term ( & self . counters_seen , & zero_expressions, * operand) {
107+ if is_zero_term ( & self . ids_info . counters_seen , & zero_expressions, * operand) {
150108 * operand = CovTerm :: Zero ;
151109 }
152110 } ;
@@ -172,17 +130,17 @@ impl<'tcx> FunctionCoverageCollector<'tcx> {
172130
173131 pub ( crate ) fn into_finished ( self ) -> FunctionCoverage < ' tcx > {
174132 let zero_expressions = self . identify_zero_expressions ( ) ;
175- let FunctionCoverageCollector { function_coverage_info, is_used , counters_seen , .. } = self ;
133+ let FunctionCoverageCollector { function_coverage_info, ids_info , is_used , .. } = self ;
176134
177- FunctionCoverage { function_coverage_info, is_used , counters_seen , zero_expressions }
135+ FunctionCoverage { function_coverage_info, ids_info , is_used , zero_expressions }
178136 }
179137}
180138
181139pub ( crate ) struct FunctionCoverage < ' tcx > {
182140 pub ( crate ) function_coverage_info : & ' tcx FunctionCoverageInfo ,
141+ ids_info : & ' tcx CoverageIdsInfo ,
183142 is_used : bool ,
184143
185- counters_seen : BitSet < CounterId > ,
186144 zero_expressions : ZeroExpressions ,
187145}
188146
@@ -238,7 +196,7 @@ impl<'tcx> FunctionCoverage<'tcx> {
238196 }
239197
240198 fn is_zero_term ( & self , term : CovTerm ) -> bool {
241- is_zero_term ( & self . counters_seen , & self . zero_expressions , term)
199+ ! self . is_used || is_zero_term ( & self . ids_info . counters_seen , & self . zero_expressions , term)
242200 }
243201}
244202
0 commit comments