@@ -2,8 +2,9 @@ use std::collections::BTreeSet;
2
2
3
3
use rustc_data_structures:: graph:: DirectedGraph ;
4
4
use rustc_index:: bit_set:: BitSet ;
5
+ use rustc_index:: IndexVec ;
5
6
use rustc_middle:: mir:: coverage:: {
6
- BlockMarkerId , BranchSpan , ConditionInfo , CoverageKind , MCDCBranchSpan , MCDCDecisionSpan ,
7
+ BlockMarkerId , BranchSpan , ConditionInfo , CoverageKind , MCDCBranchSpan ,
7
8
} ;
8
9
use rustc_middle:: mir:: { self , BasicBlock , StatementKind } ;
9
10
use rustc_span:: Span ;
@@ -13,7 +14,6 @@ use crate::coverage::spans::{
13
14
extract_refined_covspans, unexpand_into_body_span_with_visible_macro,
14
15
} ;
15
16
use crate :: coverage:: ExtractedHirInfo ;
16
- use rustc_index:: IndexVec ;
17
17
18
18
#[ derive( Clone , Debug ) ]
19
19
pub ( super ) enum BcbMappingKind {
@@ -32,13 +32,6 @@ pub(super) enum BcbMappingKind {
32
32
condition_info : Option < ConditionInfo > ,
33
33
decision_depth : u16 ,
34
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
35
}
43
36
44
37
#[ derive( Debug ) ]
@@ -57,11 +50,22 @@ pub(super) struct BcbBranchPair {
57
50
pub ( super ) false_bcb : BasicCoverageBlock ,
58
51
}
59
52
53
+ /// Associates an MC/DC decision with its join BCBs.
54
+ #[ derive( Debug ) ]
55
+ pub ( super ) struct MCDCDecision {
56
+ pub ( super ) span : Span ,
57
+ pub ( super ) end_bcbs : BTreeSet < BasicCoverageBlock > ,
58
+ pub ( super ) bitmap_idx : u32 ,
59
+ pub ( super ) conditions_num : u16 ,
60
+ pub ( super ) decision_depth : u16 ,
61
+ }
62
+
60
63
pub ( super ) struct CoverageSpans {
61
64
bcb_has_mappings : BitSet < BasicCoverageBlock > ,
62
65
pub ( super ) mappings : Vec < BcbMapping > ,
63
66
pub ( super ) branch_pairs : Vec < BcbBranchPair > ,
64
67
test_vector_bitmap_bytes : u32 ,
68
+ pub ( super ) mcdc_decisions : Vec < MCDCDecision > ,
65
69
}
66
70
67
71
impl CoverageSpans {
@@ -85,6 +89,7 @@ pub(super) fn generate_coverage_spans(
85
89
) -> Option < CoverageSpans > {
86
90
let mut mappings = vec ! [ ] ;
87
91
let mut branch_pairs = vec ! [ ] ;
92
+ let mut mcdc_decisions = vec ! [ ] ;
88
93
89
94
if hir_info. is_async_fn {
90
95
// An async function desugars into a function that returns a future,
@@ -99,10 +104,15 @@ pub(super) fn generate_coverage_spans(
99
104
100
105
branch_pairs. extend ( extract_branch_pairs ( mir_body, hir_info, basic_coverage_blocks) ) ;
101
106
102
- mappings. extend ( extract_mcdc_mappings ( mir_body, hir_info. body_span , basic_coverage_blocks) ) ;
107
+ mappings. extend ( extract_mcdc_mappings (
108
+ mir_body,
109
+ hir_info. body_span ,
110
+ basic_coverage_blocks,
111
+ & mut mcdc_decisions,
112
+ ) ) ;
103
113
}
104
114
105
- if mappings. is_empty ( ) && branch_pairs. is_empty ( ) {
115
+ if mappings. is_empty ( ) && branch_pairs. is_empty ( ) && mcdc_decisions . is_empty ( ) {
106
116
return None ;
107
117
}
108
118
@@ -111,29 +121,37 @@ pub(super) fn generate_coverage_spans(
111
121
let mut insert = |bcb| {
112
122
bcb_has_mappings. insert ( bcb) ;
113
123
} ;
114
- let mut test_vector_bitmap_bytes = 0 ;
124
+
115
125
for BcbMapping { kind, span : _ } in & mappings {
116
126
match * kind {
117
127
BcbMappingKind :: Code ( bcb) => insert ( bcb) ,
118
128
BcbMappingKind :: MCDCBranch { true_bcb, false_bcb, .. } => {
119
129
insert ( true_bcb) ;
120
130
insert ( false_bcb) ;
121
131
}
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
132
}
130
133
}
131
134
for & BcbBranchPair { true_bcb, false_bcb, .. } in & branch_pairs {
132
135
insert ( true_bcb) ;
133
136
insert ( false_bcb) ;
134
137
}
135
138
136
- Some ( CoverageSpans { bcb_has_mappings, mappings, branch_pairs, test_vector_bitmap_bytes } )
139
+ // Determine the length of the test vector bitmap.
140
+ let test_vector_bitmap_bytes = mcdc_decisions
141
+ . iter ( )
142
+ . map ( |& MCDCDecision { bitmap_idx, conditions_num, .. } | {
143
+ bitmap_idx + ( 1_u32 << u32:: from ( conditions_num) ) . div_ceil ( 8 )
144
+ } )
145
+ . max ( )
146
+ . unwrap_or ( 0 ) ;
147
+
148
+ Some ( CoverageSpans {
149
+ bcb_has_mappings,
150
+ mappings,
151
+ branch_pairs,
152
+ test_vector_bitmap_bytes,
153
+ mcdc_decisions,
154
+ } )
137
155
}
138
156
139
157
fn resolve_block_markers (
@@ -199,6 +217,7 @@ pub(super) fn extract_mcdc_mappings(
199
217
mir_body : & mir:: Body < ' _ > ,
200
218
body_span : Span ,
201
219
basic_coverage_blocks : & CoverageGraph ,
220
+ mcdc_decisions : & mut impl Extend < MCDCDecision > ,
202
221
) -> Vec < BcbMapping > {
203
222
let Some ( branch_info) = mir_body. coverage_branch_info . as_deref ( ) else {
204
223
return vec ! [ ] ;
@@ -245,31 +264,30 @@ pub(super) fn extract_mcdc_mappings(
245
264
246
265
let mut next_bitmap_idx = 0 ;
247
266
248
- let decision_filter_map = |decision : & MCDCDecisionSpan | {
249
- let ( span, _) = unexpand_into_body_span_with_visible_macro ( decision. span , body_span) ?;
267
+ mcdc_decisions. extend ( branch_info. mcdc_decision_spans . iter ( ) . filter_map (
268
+ |decision : & mir:: coverage:: MCDCDecisionSpan | {
269
+ let ( span, _) = unexpand_into_body_span_with_visible_macro ( decision. span , body_span) ?;
250
270
251
- let end_bcbs = decision
252
- . end_markers
253
- . iter ( )
254
- . map ( |& marker| bcb_from_marker ( marker) )
255
- . collect :: < Option < _ > > ( ) ?;
271
+ let end_bcbs = decision
272
+ . end_markers
273
+ . iter ( )
274
+ . map ( |& marker| bcb_from_marker ( marker) )
275
+ . collect :: < Option < _ > > ( ) ?;
256
276
257
- let bitmap_idx = next_bitmap_idx;
258
- next_bitmap_idx += ( 1_u32 << decision. conditions_num ) . div_ceil ( 8 ) ;
277
+ let bitmap_idx = next_bitmap_idx;
278
+ next_bitmap_idx += ( 1_u32 << decision. conditions_num ) . div_ceil ( 8 ) ;
259
279
260
- Some ( BcbMapping {
261
- kind : BcbMappingKind :: MCDCDecision {
280
+ Some ( MCDCDecision {
281
+ span ,
262
282
end_bcbs,
263
283
bitmap_idx,
264
284
conditions_num : decision. conditions_num as u16 ,
265
285
decision_depth : decision. decision_depth ,
266
- } ,
267
- span,
268
- } )
269
- } ;
286
+ } )
287
+ } ,
288
+ ) ) ;
270
289
271
290
std:: iter:: empty ( )
272
291
. 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
292
. collect :: < Vec < _ > > ( )
275
293
}
0 commit comments