@@ -2,9 +2,8 @@ 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_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 } ;
8
7
use rustc_middle:: mir:: { self , BasicBlock , StatementKind } ;
9
8
use rustc_span:: Span ;
10
9
@@ -13,55 +12,53 @@ use crate::coverage::spans::{
13
12
extract_refined_covspans, unexpand_into_body_span_with_visible_macro,
14
13
} ;
15
14
use 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
- }
43
15
16
+ /// Associates an ordinary executable code span with its corresponding BCB.
44
17
#[ derive( Debug ) ]
45
- pub ( super ) struct BcbMapping {
46
- pub ( super ) kind : BcbMappingKind ,
18
+ pub ( super ) struct CodeMapping {
47
19
pub ( super ) span : Span ,
20
+ pub ( super ) bcb : BasicCoverageBlock ,
48
21
}
49
22
50
- /// This is separate from [`BcbMappingKind `] to help prepare for larger changes
23
+ /// This is separate from [`MCDCBranch `] to help prepare for larger changes
51
24
/// that will be needed for improved branch coverage in the future.
52
25
/// (See <https://github.com/rust-lang/rust/pull/124217>.)
53
26
#[ derive( Debug ) ]
54
- pub ( super ) struct BcbBranchPair {
27
+ pub ( super ) struct BranchPair {
55
28
pub ( super ) span : Span ,
56
29
pub ( super ) true_bcb : BasicCoverageBlock ,
57
30
pub ( super ) false_bcb : BasicCoverageBlock ,
58
31
}
59
32
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
+
60
55
pub ( super ) struct CoverageSpans {
61
56
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 > ,
64
59
test_vector_bitmap_bytes : u32 ,
60
+ pub ( super ) mcdc_branches : Vec < MCDCBranch > ,
61
+ pub ( super ) mcdc_decisions : Vec < MCDCDecision > ,
65
62
}
66
63
67
64
impl CoverageSpans {
@@ -83,26 +80,38 @@ pub(super) fn generate_coverage_spans(
83
80
hir_info : & ExtractedHirInfo ,
84
81
basic_coverage_blocks : & CoverageGraph ,
85
82
) -> Option < CoverageSpans > {
86
- let mut mappings = vec ! [ ] ;
83
+ let mut code_mappings = vec ! [ ] ;
87
84
let mut branch_pairs = vec ! [ ] ;
85
+ let mut mcdc_branches = vec ! [ ] ;
86
+ let mut mcdc_decisions = vec ! [ ] ;
88
87
89
88
if hir_info. is_async_fn {
90
89
// An async function desugars into a function that returns a future,
91
90
// with the user code wrapped in a closure. Any spans in the desugared
92
91
// outer function will be unhelpful, so just keep the signature span
93
92
// and ignore all of the spans in the MIR body.
94
93
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 } ) ;
96
95
}
97
96
} 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 ) ;
99
98
100
99
branch_pairs. extend ( extract_branch_pairs ( mir_body, hir_info, basic_coverage_blocks) ) ;
101
100
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
+ ) ;
103
108
}
104
109
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
+ {
106
115
return None ;
107
116
}
108
117
@@ -111,29 +120,36 @@ pub(super) fn generate_coverage_spans(
111
120
let mut insert = |bcb| {
112
121
bcb_has_mappings. insert ( bcb) ;
113
122
} ;
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) ;
130
130
}
131
- for & BcbBranchPair { true_bcb, false_bcb, .. } in & branch_pairs {
131
+ for & MCDCBranch { true_bcb, false_bcb, .. } in & mcdc_branches {
132
132
insert ( true_bcb) ;
133
133
insert ( false_bcb) ;
134
134
}
135
135
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
+ } )
137
153
}
138
154
139
155
fn resolve_block_markers (
@@ -167,7 +183,7 @@ pub(super) fn extract_branch_pairs(
167
183
mir_body : & mir:: Body < ' _ > ,
168
184
hir_info : & ExtractedHirInfo ,
169
185
basic_coverage_blocks : & CoverageGraph ,
170
- ) -> Vec < BcbBranchPair > {
186
+ ) -> Vec < BranchPair > {
171
187
let Some ( branch_info) = mir_body. coverage_branch_info . as_deref ( ) else { return vec ! [ ] } ;
172
188
173
189
let block_markers = resolve_block_markers ( branch_info, mir_body) ;
@@ -190,7 +206,7 @@ pub(super) fn extract_branch_pairs(
190
206
let true_bcb = bcb_from_marker ( true_marker) ?;
191
207
let false_bcb = bcb_from_marker ( false_marker) ?;
192
208
193
- Some ( BcbBranchPair { span, true_bcb, false_bcb } )
209
+ Some ( BranchPair { span, true_bcb, false_bcb } )
194
210
} )
195
211
. collect :: < Vec < _ > > ( )
196
212
}
@@ -199,10 +215,10 @@ pub(super) fn extract_mcdc_mappings(
199
215
mir_body : & mir:: Body < ' _ > ,
200
216
body_span : Span ,
201
217
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 } ;
206
222
207
223
let block_markers = resolve_block_markers ( branch_info, mir_body) ;
208
224
@@ -223,53 +239,42 @@ pub(super) fn extract_mcdc_mappings(
223
239
Some ( ( span, true_bcb, false_bcb) )
224
240
} ;
225
241
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
+ ) ) ;
245
255
246
256
let mut next_bitmap_idx = 0 ;
247
257
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) ?;
250
261
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 < _ > > ( ) ?;
256
267
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 ) ;
259
270
260
- Some ( BcbMapping {
261
- kind : BcbMappingKind :: MCDCDecision {
271
+ Some ( MCDCDecision {
272
+ span ,
262
273
end_bcbs,
263
274
bitmap_idx,
264
275
conditions_num : decision. conditions_num as u16 ,
265
276
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
+ ) ) ;
275
280
}
0 commit comments