@@ -20,7 +20,7 @@ pub(crate) struct BranchInfoBuilder {
20
20
21
21
num_block_markers : usize ,
22
22
branch_spans : Vec < BranchSpan > ,
23
-
23
+ decision_spans : Vec < DecisionSpan > ,
24
24
mcdc_state : Option < MCDCState > ,
25
25
}
26
26
@@ -43,6 +43,7 @@ impl BranchInfoBuilder {
43
43
nots : FxHashMap :: default ( ) ,
44
44
num_block_markers : 0 ,
45
45
branch_spans : vec ! [ ] ,
46
+ decision_spans : vec ! [ ] ,
46
47
mcdc_state : MCDCState :: new_if_enabled ( tcx) ,
47
48
} )
48
49
} else {
@@ -101,13 +102,12 @@ impl BranchInfoBuilder {
101
102
}
102
103
103
104
pub ( crate ) fn into_done ( self ) -> Option < Box < mir:: coverage:: BranchInfo > > {
104
- let Self { nots : _, num_block_markers, branch_spans, mcdc_state } = self ;
105
+ let Self { nots : _, num_block_markers, branch_spans, decision_spans , .. } = self ;
105
106
106
107
if num_block_markers == 0 {
107
108
assert ! ( branch_spans. is_empty( ) ) ;
108
109
return None ;
109
110
}
110
- let decision_spans = mcdc_state. map ( |state| state. decisions ) . unwrap_or_default ( ) ;
111
111
112
112
Some ( Box :: new ( mir:: coverage:: BranchInfo {
113
113
num_block_markers,
@@ -120,22 +120,19 @@ impl BranchInfoBuilder {
120
120
/// The MCDC bitmap scales exponentially (2^n) based on the number of conditions seen,
121
121
/// So llvm sets a maximum value prevents the bitmap footprint from growing too large without the user's knowledge.
122
122
/// This limit may be relaxed if the [upstream change](https://github.com/llvm/llvm-project/pull/82448) is merged.
123
- const MAX_CONDITIONS_NUM_IN_DECISION : u16 = 6 ;
123
+ const MAX_CONDITIONS_NUM_IN_DECISION : usize = 6 ;
124
124
125
125
struct MCDCState {
126
126
/// To construct condition evaluation tree.
127
127
decision_stack : VecDeque < ConditionInfo > ,
128
128
next_condition_id : usize ,
129
- decisions : Vec < DecisionSpan > ,
130
129
}
131
130
132
131
impl MCDCState {
133
132
fn new_if_enabled ( tcx : TyCtxt < ' _ > ) -> Option < Self > {
134
- tcx. sess . instrument_coverage_mcdc ( ) . then ( || Self {
135
- decision_stack : VecDeque :: new ( ) ,
136
- next_condition_id : 0 ,
137
- decisions : vec ! [ ] ,
138
- } )
133
+ tcx. sess
134
+ . instrument_coverage_mcdc ( )
135
+ . then ( || Self { decision_stack : VecDeque :: new ( ) , next_condition_id : 0 } )
139
136
}
140
137
141
138
/// At first we assign ConditionIds for each sub expression.
@@ -278,24 +275,7 @@ impl Builder<'_, '_> {
278
275
} ) ;
279
276
}
280
277
281
- pub ( crate ) fn visit_coverage_decision ( & mut self , expr_id : ExprId ) {
282
- let Some ( branch_info) = self . coverage_branch_info . as_mut ( ) else { return } ;
283
- if branch_info. mcdc_state . is_some ( ) {
284
- let join_marker = branch_info. next_block_marker_id ( ) ;
285
- let mcdc_state = branch_info. mcdc_state . as_mut ( ) . unwrap ( ) ;
286
- assert ! (
287
- mcdc_state. decision_stack. is_empty( ) && mcdc_state. next_condition_id == 0 ,
288
- "There is a unfinished decision"
289
- ) ;
290
- mcdc_state. decisions . push ( DecisionSpan {
291
- span : self . thir [ expr_id] . span ,
292
- conditions_num : 0 ,
293
- join_marker,
294
- } ) ;
295
- }
296
- }
297
-
298
- pub ( crate ) fn visit_coverage_decision_end ( & mut self , join_block : BasicBlock ) {
278
+ pub ( crate ) fn visit_coverage_decision ( & mut self , expr_id : ExprId , join_block : BasicBlock ) {
299
279
if let Some ( ( mcdc_state, branches) ) = self
300
280
. coverage_branch_info
301
281
. as_mut ( )
@@ -305,18 +285,26 @@ impl Builder<'_, '_> {
305
285
mcdc_state. decision_stack. is_empty( ) ,
306
286
"All condition should have been checked before the decision ends"
307
287
) ;
308
- let Some ( decision) = mcdc_state. decisions . last_mut ( ) else { return } ;
309
288
310
- decision. conditions_num = mcdc_state. next_condition_id as u16 ;
289
+ let conditions_num = mcdc_state. next_condition_id ;
290
+
311
291
mcdc_state. next_condition_id = 0 ;
312
292
313
- match decision . conditions_num {
293
+ match conditions_num {
314
294
0 => {
315
295
unreachable ! ( "Decision with no conditions is not allowed" ) ;
316
296
}
317
297
1 ..=MAX_CONDITIONS_NUM_IN_DECISION => {
318
- let span = decision. span ;
319
- let id = decision. join_marker ;
298
+ let span = self . thir [ expr_id] . span ;
299
+ let branch_info =
300
+ self . coverage_branch_info . as_mut ( ) . expect ( "updating to existed" ) ;
301
+ let id = branch_info. next_block_marker_id ( ) ;
302
+
303
+ branch_info. decision_spans . push ( DecisionSpan {
304
+ span,
305
+ conditions_num : conditions_num as u16 ,
306
+ join_marker : id,
307
+ } ) ;
320
308
321
309
let statement = mir:: Statement {
322
310
source_info : self . source_info ( span) ,
@@ -326,16 +314,15 @@ impl Builder<'_, '_> {
326
314
}
327
315
_ => {
328
316
// Do not generate mcdc mappings and statements for decisions with too many conditions.
329
- for branch in branches. iter_mut ( ) . rev ( ) . take ( decision . conditions_num as usize ) {
317
+ for branch in branches. iter_mut ( ) . rev ( ) . take ( conditions_num) {
330
318
branch. condition_info = Default :: default ( ) ;
331
319
}
332
320
333
321
self . tcx . dcx ( ) . emit_warn ( MCDCExceedsConditionNumLimit {
334
- span : decision . span ,
335
- conditions_num : decision . conditions_num ,
322
+ span : self . thir [ expr_id ] . span ,
323
+ conditions_num,
336
324
max_conditions_num : MAX_CONDITIONS_NUM_IN_DECISION ,
337
325
} ) ;
338
- mcdc_state. decisions . pop ( ) ;
339
326
}
340
327
}
341
328
}
0 commit comments