Auto merge of #124255 - RenjiSann:renji/mcdc-nested-expressions, r=Zalathar
MCDC coverage: support nested decision coverage #123409 provided the initial MCDC coverage implementation. As referenced in #124144, it does not currently support "nested" decisions, like the following example : ```rust fn nested_if_in_condition(a: bool, b: bool, c: bool) { if a && if b || c { true } else { false } { say("yes"); } else { say("no"); } } ``` Note that there is an if-expression (`if b || c ...`) embedded inside a boolean expression in the decision of an outer if-expression. This PR proposes a workaround for this cases, by introducing a Decision context stack, and by handing several `temporary condition bitmaps` instead of just one. When instrumenting boolean expressions, if the current node is a leaf condition (i.e. not a `||`/`&&` logical operator nor a `!` not operator), we insert a new decision context, such that if there are more boolean expressions inside the condition, they are handled as separate expressions. On the codegen LLVM side, we allocate as many `temp_cond_bitmap`s as necessary to handle the maximum encountered decision depth.
This commit is contained in:
commit
7a58674259
12 changed files with 699 additions and 70 deletions
|
@ -132,7 +132,7 @@ pub enum CoverageKind {
|
|||
///
|
||||
/// If this statement does not survive MIR optimizations, the condition would never be
|
||||
/// taken as evaluated.
|
||||
CondBitmapUpdate { id: ConditionId, value: bool },
|
||||
CondBitmapUpdate { id: ConditionId, value: bool, decision_depth: u16 },
|
||||
|
||||
/// Marks the point in MIR control flow represented by a evaluated decision.
|
||||
///
|
||||
|
@ -140,7 +140,7 @@ pub enum CoverageKind {
|
|||
///
|
||||
/// If this statement does not survive MIR optimizations, the decision would never be
|
||||
/// taken as evaluated.
|
||||
TestVectorBitmapUpdate { bitmap_idx: u32 },
|
||||
TestVectorBitmapUpdate { bitmap_idx: u32, decision_depth: u16 },
|
||||
}
|
||||
|
||||
impl Debug for CoverageKind {
|
||||
|
@ -151,11 +151,17 @@ impl Debug for CoverageKind {
|
|||
BlockMarker { id } => write!(fmt, "BlockMarker({:?})", id.index()),
|
||||
CounterIncrement { id } => write!(fmt, "CounterIncrement({:?})", id.index()),
|
||||
ExpressionUsed { id } => write!(fmt, "ExpressionUsed({:?})", id.index()),
|
||||
CondBitmapUpdate { id, value } => {
|
||||
write!(fmt, "CondBitmapUpdate({:?}, {:?})", id.index(), value)
|
||||
CondBitmapUpdate { id, value, decision_depth } => {
|
||||
write!(
|
||||
fmt,
|
||||
"CondBitmapUpdate({:?}, {:?}, depth={:?})",
|
||||
id.index(),
|
||||
value,
|
||||
decision_depth
|
||||
)
|
||||
}
|
||||
TestVectorBitmapUpdate { bitmap_idx } => {
|
||||
write!(fmt, "TestVectorUpdate({:?})", bitmap_idx)
|
||||
TestVectorBitmapUpdate { bitmap_idx, decision_depth } => {
|
||||
write!(fmt, "TestVectorUpdate({:?}, depth={:?})", bitmap_idx, decision_depth)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -269,6 +275,9 @@ pub struct FunctionCoverageInfo {
|
|||
pub mcdc_bitmap_bytes: u32,
|
||||
pub expressions: IndexVec<ExpressionId, Expression>,
|
||||
pub mappings: Vec<Mapping>,
|
||||
/// The depth of the deepest decision is used to know how many
|
||||
/// temp condbitmaps should be allocated for the function.
|
||||
pub mcdc_max_decision_depth: u16,
|
||||
}
|
||||
|
||||
/// Branch information recorded during THIR-to-MIR lowering, and stored in MIR.
|
||||
|
@ -319,6 +328,7 @@ pub struct MCDCBranchSpan {
|
|||
pub condition_info: Option<ConditionInfo>,
|
||||
pub true_marker: BlockMarkerId,
|
||||
pub false_marker: BlockMarkerId,
|
||||
pub decision_depth: u16,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
|
@ -334,4 +344,5 @@ pub struct MCDCDecisionSpan {
|
|||
pub span: Span,
|
||||
pub conditions_num: usize,
|
||||
pub end_markers: Vec<BlockMarkerId>,
|
||||
pub decision_depth: u16,
|
||||
}
|
||||
|
|
|
@ -496,20 +496,27 @@ fn write_coverage_branch_info(
|
|||
)?;
|
||||
}
|
||||
|
||||
for coverage::MCDCBranchSpan { span, condition_info, true_marker, false_marker } in
|
||||
mcdc_branch_spans
|
||||
for coverage::MCDCBranchSpan {
|
||||
span,
|
||||
condition_info,
|
||||
true_marker,
|
||||
false_marker,
|
||||
decision_depth,
|
||||
} in mcdc_branch_spans
|
||||
{
|
||||
writeln!(
|
||||
w,
|
||||
"{INDENT}coverage mcdc branch {{ condition_id: {:?}, true: {true_marker:?}, false: {false_marker:?} }} => {span:?}",
|
||||
"{INDENT}coverage mcdc branch {{ condition_id: {:?}, true: {true_marker:?}, false: {false_marker:?}, depth: {decision_depth:?} }} => {span:?}",
|
||||
condition_info.map(|info| info.condition_id)
|
||||
)?;
|
||||
}
|
||||
|
||||
for coverage::MCDCDecisionSpan { span, conditions_num, end_markers } in mcdc_decision_spans {
|
||||
for coverage::MCDCDecisionSpan { span, conditions_num, end_markers, decision_depth } in
|
||||
mcdc_decision_spans
|
||||
{
|
||||
writeln!(
|
||||
w,
|
||||
"{INDENT}coverage mcdc decision {{ conditions_num: {conditions_num:?}, end: {end_markers:?} }} => {span:?}"
|
||||
"{INDENT}coverage mcdc decision {{ conditions_num: {conditions_num:?}, end: {end_markers:?}, depth: {decision_depth:?} }} => {span:?}"
|
||||
)?;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue