@@ -2,9 +2,8 @@ use std::collections::BTreeSet;
22
33use rustc_data_structures:: graph:: DirectedGraph ;
44use rustc_index:: bit_set:: BitSet ;
5- use rustc_middle:: mir:: coverage:: {
6- BlockMarkerId , BranchSpan , ConditionInfo , CoverageKind , MCDCBranchSpan , MCDCDecisionSpan ,
7- } ;
5+ use rustc_index:: IndexVec ;
6+ use rustc_middle:: mir:: coverage:: { BlockMarkerId , BranchSpan , ConditionInfo , CoverageKind } ;
87use rustc_middle:: mir:: { self , BasicBlock , StatementKind } ;
98use rustc_span:: Span ;
109
@@ -13,55 +12,53 @@ use crate::coverage::spans::{
1312 extract_refined_covspans, unexpand_into_body_span_with_visible_macro,
1413} ;
1514use crate :: coverage:: ExtractedHirInfo ;
16- use rustc_index:: IndexVec ;
17-
18- #[ derive( Clone , Debug ) ]
19- pub ( super ) enum BcbMappingKind {
20- /// Associates an ordinary executable code span with its corresponding BCB.
21- Code ( BasicCoverageBlock ) ,
22-
23- // Ordinary branch mappings are stored separately, so they don't have a
24- // variant in this enum.
25- //
26- /// Associates a mcdc branch span with condition info besides fields for normal branch.
27- MCDCBranch {
28- true_bcb : BasicCoverageBlock ,
29- false_bcb : BasicCoverageBlock ,
30- /// If `None`, this actually represents a normal branch mapping inserted
31- /// for code that was too complex for MC/DC.
32- condition_info : Option < ConditionInfo > ,
33- decision_depth : u16 ,
34- } ,
35- /// Associates a mcdc decision with its join BCB.
36- MCDCDecision {
37- end_bcbs : BTreeSet < BasicCoverageBlock > ,
38- bitmap_idx : u32 ,
39- conditions_num : u16 ,
40- decision_depth : u16 ,
41- } ,
42- }
4315
16+ /// Associates an ordinary executable code span with its corresponding BCB.
4417#[ derive( Debug ) ]
45- pub ( super ) struct BcbMapping {
46- pub ( super ) kind : BcbMappingKind ,
18+ pub ( super ) struct CodeMapping {
4719 pub ( super ) span : Span ,
20+ pub ( super ) bcb : BasicCoverageBlock ,
4821}
4922
50- /// This is separate from [`BcbMappingKind `] to help prepare for larger changes
23+ /// This is separate from [`MCDCBranch `] to help prepare for larger changes
5124/// that will be needed for improved branch coverage in the future.
5225/// (See <https://github.com/rust-lang/rust/pull/124217>.)
5326#[ derive( Debug ) ]
54- pub ( super ) struct BcbBranchPair {
27+ pub ( super ) struct BranchPair {
5528 pub ( super ) span : Span ,
5629 pub ( super ) true_bcb : BasicCoverageBlock ,
5730 pub ( super ) false_bcb : BasicCoverageBlock ,
5831}
5932
33+ /// Associates an MC/DC branch span with condition info besides fields for normal branch.
34+ #[ derive( Debug ) ]
35+ pub ( super ) struct MCDCBranch {
36+ pub ( super ) span : Span ,
37+ pub ( super ) true_bcb : BasicCoverageBlock ,
38+ pub ( super ) false_bcb : BasicCoverageBlock ,
39+ /// If `None`, this actually represents a normal branch mapping inserted
40+ /// for code that was too complex for MC/DC.
41+ pub ( super ) condition_info : Option < ConditionInfo > ,
42+ pub ( super ) decision_depth : u16 ,
43+ }
44+
45+ /// Associates an MC/DC decision with its join BCBs.
46+ #[ derive( Debug ) ]
47+ pub ( super ) struct MCDCDecision {
48+ pub ( super ) span : Span ,
49+ pub ( super ) end_bcbs : BTreeSet < BasicCoverageBlock > ,
50+ pub ( super ) bitmap_idx : u32 ,
51+ pub ( super ) conditions_num : u16 ,
52+ pub ( super ) decision_depth : u16 ,
53+ }
54+
6055pub ( super ) struct CoverageSpans {
6156 bcb_has_mappings : BitSet < BasicCoverageBlock > ,
62- pub ( super ) mappings : Vec < BcbMapping > ,
63- pub ( super ) branch_pairs : Vec < BcbBranchPair > ,
57+ pub ( super ) code_mappings : Vec < CodeMapping > ,
58+ pub ( super ) branch_pairs : Vec < BranchPair > ,
6459 test_vector_bitmap_bytes : u32 ,
60+ pub ( super ) mcdc_branches : Vec < MCDCBranch > ,
61+ pub ( super ) mcdc_decisions : Vec < MCDCDecision > ,
6562}
6663
6764impl CoverageSpans {
@@ -83,26 +80,38 @@ pub(super) fn generate_coverage_spans(
8380 hir_info : & ExtractedHirInfo ,
8481 basic_coverage_blocks : & CoverageGraph ,
8582) -> Option < CoverageSpans > {
86- let mut mappings = vec ! [ ] ;
83+ let mut code_mappings = vec ! [ ] ;
8784 let mut branch_pairs = vec ! [ ] ;
85+ let mut mcdc_branches = vec ! [ ] ;
86+ let mut mcdc_decisions = vec ! [ ] ;
8887
8988 if hir_info. is_async_fn {
9089 // An async function desugars into a function that returns a future,
9190 // with the user code wrapped in a closure. Any spans in the desugared
9291 // outer function will be unhelpful, so just keep the signature span
9392 // and ignore all of the spans in the MIR body.
9493 if let Some ( span) = hir_info. fn_sig_span_extended {
95- mappings . push ( BcbMapping { kind : BcbMappingKind :: Code ( START_BCB ) , span } ) ;
94+ code_mappings . push ( CodeMapping { span , bcb : START_BCB } ) ;
9695 }
9796 } else {
98- extract_refined_covspans ( mir_body, hir_info, basic_coverage_blocks, & mut mappings ) ;
97+ extract_refined_covspans ( mir_body, hir_info, basic_coverage_blocks, & mut code_mappings ) ;
9998
10099 branch_pairs. extend ( extract_branch_pairs ( mir_body, hir_info, basic_coverage_blocks) ) ;
101100
102- mappings. extend ( extract_mcdc_mappings ( mir_body, hir_info. body_span , basic_coverage_blocks) ) ;
101+ extract_mcdc_mappings (
102+ mir_body,
103+ hir_info. body_span ,
104+ basic_coverage_blocks,
105+ & mut mcdc_branches,
106+ & mut mcdc_decisions,
107+ ) ;
103108 }
104109
105- if mappings. is_empty ( ) && branch_pairs. is_empty ( ) {
110+ if code_mappings. is_empty ( )
111+ && branch_pairs. is_empty ( )
112+ && mcdc_branches. is_empty ( )
113+ && mcdc_decisions. is_empty ( )
114+ {
106115 return None ;
107116 }
108117
@@ -111,29 +120,36 @@ pub(super) fn generate_coverage_spans(
111120 let mut insert = |bcb| {
112121 bcb_has_mappings. insert ( bcb) ;
113122 } ;
114- let mut test_vector_bitmap_bytes = 0 ;
115- for BcbMapping { kind, span : _ } in & mappings {
116- match * kind {
117- BcbMappingKind :: Code ( bcb) => insert ( bcb) ,
118- BcbMappingKind :: MCDCBranch { true_bcb, false_bcb, .. } => {
119- insert ( true_bcb) ;
120- insert ( false_bcb) ;
121- }
122- BcbMappingKind :: MCDCDecision { bitmap_idx, conditions_num, .. } => {
123- // `bcb_has_mappings` is used for inject coverage counters
124- // but they are not needed for decision BCBs.
125- // While the length of test vector bitmap should be calculated here.
126- test_vector_bitmap_bytes = test_vector_bitmap_bytes
127- . max ( bitmap_idx + ( 1_u32 << conditions_num as u32 ) . div_ceil ( 8 ) ) ;
128- }
129- }
123+
124+ for & CodeMapping { span : _, bcb } in & code_mappings {
125+ insert ( bcb) ;
126+ }
127+ for & BranchPair { true_bcb, false_bcb, .. } in & branch_pairs {
128+ insert ( true_bcb) ;
129+ insert ( false_bcb) ;
130130 }
131- for & BcbBranchPair { true_bcb, false_bcb, .. } in & branch_pairs {
131+ for & MCDCBranch { true_bcb, false_bcb, .. } in & mcdc_branches {
132132 insert ( true_bcb) ;
133133 insert ( false_bcb) ;
134134 }
135135
136- Some ( CoverageSpans { bcb_has_mappings, mappings, branch_pairs, test_vector_bitmap_bytes } )
136+ // Determine the length of the test vector bitmap.
137+ let test_vector_bitmap_bytes = mcdc_decisions
138+ . iter ( )
139+ . map ( |& MCDCDecision { bitmap_idx, conditions_num, .. } | {
140+ bitmap_idx + ( 1_u32 << u32:: from ( conditions_num) ) . div_ceil ( 8 )
141+ } )
142+ . max ( )
143+ . unwrap_or ( 0 ) ;
144+
145+ Some ( CoverageSpans {
146+ bcb_has_mappings,
147+ code_mappings,
148+ branch_pairs,
149+ test_vector_bitmap_bytes,
150+ mcdc_branches,
151+ mcdc_decisions,
152+ } )
137153}
138154
139155fn resolve_block_markers (
@@ -167,7 +183,7 @@ pub(super) fn extract_branch_pairs(
167183 mir_body : & mir:: Body < ' _ > ,
168184 hir_info : & ExtractedHirInfo ,
169185 basic_coverage_blocks : & CoverageGraph ,
170- ) -> Vec < BcbBranchPair > {
186+ ) -> Vec < BranchPair > {
171187 let Some ( branch_info) = mir_body. coverage_branch_info . as_deref ( ) else { return vec ! [ ] } ;
172188
173189 let block_markers = resolve_block_markers ( branch_info, mir_body) ;
@@ -190,7 +206,7 @@ pub(super) fn extract_branch_pairs(
190206 let true_bcb = bcb_from_marker ( true_marker) ?;
191207 let false_bcb = bcb_from_marker ( false_marker) ?;
192208
193- Some ( BcbBranchPair { span, true_bcb, false_bcb } )
209+ Some ( BranchPair { span, true_bcb, false_bcb } )
194210 } )
195211 . collect :: < Vec < _ > > ( )
196212}
@@ -199,10 +215,10 @@ pub(super) fn extract_mcdc_mappings(
199215 mir_body : & mir:: Body < ' _ > ,
200216 body_span : Span ,
201217 basic_coverage_blocks : & CoverageGraph ,
202- ) -> Vec < BcbMapping > {
203- let Some ( branch_info ) = mir_body . coverage_branch_info . as_deref ( ) else {
204- return vec ! [ ] ;
205- } ;
218+ mcdc_branches : & mut impl Extend < MCDCBranch > ,
219+ mcdc_decisions : & mut impl Extend < MCDCDecision > ,
220+ ) {
221+ let Some ( branch_info ) = mir_body . coverage_branch_info . as_deref ( ) else { return } ;
206222
207223 let block_markers = resolve_block_markers ( branch_info, mir_body) ;
208224
@@ -223,53 +239,42 @@ pub(super) fn extract_mcdc_mappings(
223239 Some ( ( span, true_bcb, false_bcb) )
224240 } ;
225241
226- let mcdc_branch_filter_map = |& MCDCBranchSpan {
227- span : raw_span,
228- true_marker,
229- false_marker,
230- condition_info,
231- decision_depth,
232- } | {
233- check_branch_bcb ( raw_span, true_marker, false_marker) . map ( |( span, true_bcb, false_bcb) | {
234- BcbMapping {
235- kind : BcbMappingKind :: MCDCBranch {
236- true_bcb,
237- false_bcb,
238- condition_info,
239- decision_depth,
240- } ,
241- span,
242- }
243- } )
244- } ;
242+ mcdc_branches. extend ( branch_info. mcdc_branch_spans . iter ( ) . filter_map (
243+ |& mir:: coverage:: MCDCBranchSpan {
244+ span : raw_span,
245+ condition_info,
246+ true_marker,
247+ false_marker,
248+ decision_depth,
249+ } | {
250+ let ( span, true_bcb, false_bcb) =
251+ check_branch_bcb ( raw_span, true_marker, false_marker) ?;
252+ Some ( MCDCBranch { span, true_bcb, false_bcb, condition_info, decision_depth } )
253+ } ,
254+ ) ) ;
245255
246256 let mut next_bitmap_idx = 0 ;
247257
248- let decision_filter_map = |decision : & MCDCDecisionSpan | {
249- let ( span, _) = unexpand_into_body_span_with_visible_macro ( decision. span , body_span) ?;
258+ mcdc_decisions. extend ( branch_info. mcdc_decision_spans . iter ( ) . filter_map (
259+ |decision : & mir:: coverage:: MCDCDecisionSpan | {
260+ let ( span, _) = unexpand_into_body_span_with_visible_macro ( decision. span , body_span) ?;
250261
251- let end_bcbs = decision
252- . end_markers
253- . iter ( )
254- . map ( |& marker| bcb_from_marker ( marker) )
255- . collect :: < Option < _ > > ( ) ?;
262+ let end_bcbs = decision
263+ . end_markers
264+ . iter ( )
265+ . map ( |& marker| bcb_from_marker ( marker) )
266+ . collect :: < Option < _ > > ( ) ?;
256267
257- let bitmap_idx = next_bitmap_idx;
258- next_bitmap_idx += ( 1_u32 << decision. conditions_num ) . div_ceil ( 8 ) ;
268+ let bitmap_idx = next_bitmap_idx;
269+ next_bitmap_idx += ( 1_u32 << decision. conditions_num ) . div_ceil ( 8 ) ;
259270
260- Some ( BcbMapping {
261- kind : BcbMappingKind :: MCDCDecision {
271+ Some ( MCDCDecision {
272+ span ,
262273 end_bcbs,
263274 bitmap_idx,
264275 conditions_num : decision. conditions_num as u16 ,
265276 decision_depth : decision. decision_depth ,
266- } ,
267- span,
268- } )
269- } ;
270-
271- std:: iter:: empty ( )
272- . chain ( branch_info. mcdc_branch_spans . iter ( ) . filter_map ( mcdc_branch_filter_map) )
273- . chain ( branch_info. mcdc_decision_spans . iter ( ) . filter_map ( decision_filter_map) )
274- . collect :: < Vec < _ > > ( )
277+ } )
278+ } ,
279+ ) ) ;
275280}
0 commit comments