Skip to content

Commit 1e6e3fb

Browse files
author
zhuyunxing
committed
coverage. Group MCDC decisions and conditions until instrument mappings and support multiple branch markers
1 parent 6e70bea commit 1e6e3fb

File tree

7 files changed

+263
-173
lines changed

7 files changed

+263
-173
lines changed

compiler/rustc_middle/src/mir/coverage.rs

+11-10
Original file line numberDiff line numberDiff line change
@@ -297,8 +297,10 @@ pub struct CoverageInfoHi {
297297
/// data structures without having to scan the entire body first.
298298
pub num_block_markers: usize,
299299
pub branch_spans: Vec<BranchSpan>,
300-
pub mcdc_branch_spans: Vec<MCDCBranchSpan>,
301-
pub mcdc_decision_spans: Vec<MCDCDecisionSpan>,
300+
/// Branch spans generated by mcdc. Because of some limits mcdc builder give up generating
301+
/// decisions including them so that they are handled as normal branch spans.
302+
pub mcdc_degraded_spans: Vec<MCDCBranchSpan>,
303+
pub mcdc_spans: Vec<(MCDCDecisionSpan, Vec<MCDCBranchSpan>)>,
302304
}
303305

304306
#[derive(Clone, Debug)]
@@ -331,12 +333,12 @@ impl Default for ConditionInfo {
331333
#[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)]
332334
pub struct MCDCBranchSpan {
333335
pub span: Span,
334-
/// If `None`, this actually represents a normal branch span inserted for
335-
/// code that was too complex for MC/DC.
336-
pub condition_info: Option<ConditionInfo>,
337-
pub true_marker: BlockMarkerId,
338-
pub false_marker: BlockMarkerId,
339-
pub decision_depth: u16,
336+
pub condition_info: ConditionInfo,
337+
// For boolean decisions and most pattern matching decisions there is only
338+
// one true marker and one false marker in each branch. But for matching decisions
339+
// with `|` there can be several.
340+
pub true_markers: Vec<BlockMarkerId>,
341+
pub false_markers: Vec<BlockMarkerId>,
340342
}
341343

342344
#[derive(Copy, Clone, Debug)]
@@ -350,13 +352,12 @@ pub struct DecisionInfo {
350352
#[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)]
351353
pub struct MCDCDecisionSpan {
352354
pub span: Span,
353-
pub num_conditions: usize,
354355
pub end_markers: Vec<BlockMarkerId>,
355356
pub decision_depth: u16,
356357
}
357358

358359
impl MCDCDecisionSpan {
359360
pub fn new(span: Span) -> Self {
360-
Self { span, num_conditions: 0, end_markers: Vec::new(), decision_depth: 0 }
361+
Self { span, end_markers: Vec::new(), decision_depth: 0 }
361362
}
362363
}

compiler/rustc_middle/src/mir/pretty.rs

+15-14
Original file line numberDiff line numberDiff line change
@@ -490,8 +490,8 @@ fn write_coverage_info_hi(
490490
let coverage::CoverageInfoHi {
491491
num_block_markers: _,
492492
branch_spans,
493-
mcdc_branch_spans,
494-
mcdc_decision_spans,
493+
mcdc_degraded_spans,
494+
mcdc_spans,
495495
} = coverage_info_hi;
496496

497497
// Only add an extra trailing newline if we printed at least one thing.
@@ -505,29 +505,30 @@ fn write_coverage_info_hi(
505505
did_print = true;
506506
}
507507

508-
for coverage::MCDCBranchSpan {
509-
span,
510-
condition_info,
511-
true_marker,
512-
false_marker,
513-
decision_depth,
514-
} in mcdc_branch_spans
515-
{
508+
for coverage::MCDCBranchSpan { span, true_markers, false_markers, .. } in mcdc_degraded_spans {
516509
writeln!(
517510
w,
518-
"{INDENT}coverage mcdc branch {{ condition_id: {:?}, true: {true_marker:?}, false: {false_marker:?}, depth: {decision_depth:?} }} => {span:?}",
519-
condition_info.map(|info| info.condition_id)
511+
"{INDENT}coverage branch {{ true: {true_markers:?}, false: {false_markers:?} }} => {span:?}",
520512
)?;
521513
did_print = true;
522514
}
523515

524-
for coverage::MCDCDecisionSpan { span, num_conditions, end_markers, decision_depth } in
525-
mcdc_decision_spans
516+
for (coverage::MCDCDecisionSpan { span, end_markers, decision_depth }, conditions) in mcdc_spans
526517
{
518+
let num_conditions = conditions.len();
527519
writeln!(
528520
w,
529521
"{INDENT}coverage mcdc decision {{ num_conditions: {num_conditions:?}, end: {end_markers:?}, depth: {decision_depth:?} }} => {span:?}"
530522
)?;
523+
for coverage::MCDCBranchSpan { span, condition_info, true_markers, false_markers } in
524+
conditions
525+
{
526+
writeln!(
527+
w,
528+
"{INDENT}coverage mcdc branch {{ condition_id: {:?}, true: {true_markers:?}, false: {false_markers:?} }} => {span:?}",
529+
condition_info.condition_id
530+
)?;
531+
}
531532
did_print = true;
532533
}
533534

compiler/rustc_mir_build/src/build/coverageinfo.rs

+3-8
Original file line numberDiff line numberDiff line change
@@ -175,21 +175,16 @@ impl CoverageInfoBuilder {
175175
let branch_spans =
176176
branch_info.map(|branch_info| branch_info.branch_spans).unwrap_or_default();
177177

178-
let (mut mcdc_branch_spans, mcdc_spans) =
178+
let (mcdc_degraded_spans, mcdc_spans) =
179179
mcdc_info.map(MCDCInfoBuilder::into_done).unwrap_or_default();
180-
let mut mcdc_decision_spans = Vec::with_capacity(mcdc_spans.len());
181-
for (decision, conditions) in mcdc_spans {
182-
mcdc_branch_spans.extend(conditions);
183-
mcdc_decision_spans.push(decision);
184-
}
185180

186181
// For simplicity, always return an info struct (without Option), even
187182
// if there's nothing interesting in it.
188183
Box::new(CoverageInfoHi {
189184
num_block_markers,
190185
branch_spans,
191-
mcdc_branch_spans,
192-
mcdc_decision_spans,
186+
mcdc_degraded_spans,
187+
mcdc_spans,
193188
})
194189
}
195190
}

compiler/rustc_mir_build/src/build/coverageinfo/mcdc.rs

+15-12
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ struct BooleanDecisionCtx {
3131
/// To construct condition evaluation tree.
3232
decision_stack: VecDeque<ConditionInfo>,
3333
conditions: Vec<MCDCBranchSpan>,
34+
condition_id_counter: usize,
3435
}
3536

3637
impl BooleanDecisionCtx {
@@ -40,9 +41,15 @@ impl BooleanDecisionCtx {
4041
decision_info: MCDCDecisionSpan::new(Span::default()),
4142
decision_stack: VecDeque::new(),
4243
conditions: vec![],
44+
condition_id_counter: 0,
4345
}
4446
}
4547

48+
fn next_condition_id(&mut self) -> ConditionId {
49+
self.condition_id_counter += 1;
50+
ConditionId::from_usize(self.condition_id_counter)
51+
}
52+
4653
// At first we assign ConditionIds for each sub expression.
4754
// If the sub expression is composite, re-assign its ConditionId to its LHS and generate a new ConditionId for its RHS.
4855
//
@@ -86,14 +93,12 @@ impl BooleanDecisionCtx {
8693
fn record_conditions(&mut self, op: LogicalOp) {
8794
let parent_condition = self.decision_stack.pop_back().unwrap_or_default();
8895
let lhs_id = if parent_condition.condition_id == ConditionId::NONE {
89-
self.decision_info.num_conditions += 1;
90-
ConditionId::from(self.decision_info.num_conditions)
96+
ConditionId::from(self.next_condition_id())
9197
} else {
9298
parent_condition.condition_id
9399
};
94100

95-
self.decision_info.num_conditions += 1;
96-
let rhs_condition_id = ConditionId::from(self.decision_info.num_conditions);
101+
let rhs_condition_id = self.next_condition_id();
97102

98103
let (lhs, rhs) = match op {
99104
LogicalOp::And => {
@@ -144,13 +149,10 @@ impl BooleanDecisionCtx {
144149

145150
self.conditions.push(MCDCBranchSpan {
146151
span,
147-
condition_info: Some(condition_info),
148-
true_marker,
149-
false_marker,
150-
decision_depth: 0,
152+
condition_info,
153+
true_markers: vec![true_marker],
154+
false_markers: vec![false_marker],
151155
});
152-
// In case this decision had only one condition
153-
self.decision_info.num_conditions = self.decision_info.num_conditions.max(1);
154156
}
155157

156158
fn is_finished(&self) -> bool {
@@ -244,7 +246,6 @@ struct MCDCTargetInfo {
244246
impl MCDCTargetInfo {
245247
fn set_depth(&mut self, depth: u16) {
246248
self.decision.decision_depth = depth;
247-
self.conditions.iter_mut().for_each(|branch| branch.decision_depth = depth);
248249
}
249250
}
250251

@@ -338,7 +339,9 @@ impl MCDCInfoBuilder {
338339
}
339340

340341
fn append_normal_branches(&mut self, mut branches: Vec<MCDCBranchSpan>) {
341-
branches.iter_mut().for_each(|branch| branch.condition_info = None);
342+
branches
343+
.iter_mut()
344+
.for_each(|branch| branch.condition_info.condition_id = ConditionId::NONE);
342345
self.normal_branch_spans.extend(branches);
343346
}
344347

compiler/rustc_mir_transform/src/coverage/counters.rs

+11-2
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,12 @@ impl CoverageCounters {
101101
BcbCounter::Counter { id }
102102
}
103103

104-
fn make_expression(&mut self, lhs: BcbCounter, op: Op, rhs: BcbCounter) -> BcbCounter {
104+
pub(super) fn make_expression(
105+
&mut self,
106+
lhs: BcbCounter,
107+
op: Op,
108+
rhs: BcbCounter,
109+
) -> BcbCounter {
105110
let new_expr = BcbExpression { lhs, op, rhs };
106111
*self
107112
.expressions_memo
@@ -159,7 +164,11 @@ impl CoverageCounters {
159164
/// Variant of `make_expression` that makes `lhs` optional and assumes [`Op::Add`].
160165
///
161166
/// This is useful when using [`Iterator::fold`] to build an arbitrary-length sum.
162-
fn make_sum_expression(&mut self, lhs: Option<BcbCounter>, rhs: BcbCounter) -> BcbCounter {
167+
pub(super) fn make_sum_expression(
168+
&mut self,
169+
lhs: Option<BcbCounter>,
170+
rhs: BcbCounter,
171+
) -> BcbCounter {
163172
let Some(lhs) = lhs else { return rhs };
164173
self.make_expression(lhs, Op::Add, rhs)
165174
}

0 commit comments

Comments
 (0)