coverage. Generate Mappings of decisions and conditions for MC/DC
This commit is contained in:
parent
68f86381ee
commit
cf6b6cb2b4
10 changed files with 779 additions and 41 deletions
|
@ -51,6 +51,25 @@ rustc_index::newtype_index! {
|
|||
pub struct ExpressionId {}
|
||||
}
|
||||
|
||||
rustc_index::newtype_index! {
|
||||
/// ID of a mcdc condition. Used by llvm to check mcdc coverage.
|
||||
///
|
||||
/// Note for future: the max limit of 0xFFFF is probably too loose. Actually llvm does not
|
||||
/// support decisions with too many conditions (7 and more at LLVM 18 while may be hundreds at 19)
|
||||
/// and represents it with `int16_t`. This max value may be changed once we could
|
||||
/// figure out an accurate limit.
|
||||
#[derive(HashStable)]
|
||||
#[encodable]
|
||||
#[orderable]
|
||||
#[max = 0xFFFF]
|
||||
#[debug_format = "ConditionId({})"]
|
||||
pub struct ConditionId {}
|
||||
}
|
||||
|
||||
impl ConditionId {
|
||||
pub const NONE: Self = Self::from_u32(0);
|
||||
}
|
||||
|
||||
/// Enum that can hold a constant zero value, the ID of an physical coverage
|
||||
/// counter, or the ID of a coverage-counter expression.
|
||||
///
|
||||
|
@ -106,6 +125,22 @@ pub enum CoverageKind {
|
|||
/// mappings. Intermediate expressions with no direct mappings are
|
||||
/// retained/zeroed based on whether they are transitively used.)
|
||||
ExpressionUsed { id: ExpressionId },
|
||||
|
||||
/// Marks the point in MIR control flow represented by a evaluated condition.
|
||||
///
|
||||
/// This is eventually lowered to `llvm.instrprof.mcdc.condbitmap.update` in LLVM IR.
|
||||
///
|
||||
/// If this statement does not survive MIR optimizations, the condition would never be
|
||||
/// taken as evaluated.
|
||||
CondBitmapUpdate { id: ConditionId, value: bool },
|
||||
|
||||
/// Marks the point in MIR control flow represented by a evaluated decision.
|
||||
///
|
||||
/// This is eventually lowered to `llvm.instrprof.mcdc.tvbitmap.update` in LLVM IR.
|
||||
///
|
||||
/// If this statement does not survive MIR optimizations, the decision would never be
|
||||
/// taken as evaluated.
|
||||
TestVectorBitmapUpdate { bitmap_idx: u32 },
|
||||
}
|
||||
|
||||
impl Debug for CoverageKind {
|
||||
|
@ -116,6 +151,12 @@ 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)
|
||||
}
|
||||
TestVectorBitmapUpdate { bitmap_idx } => {
|
||||
write!(fmt, "TestVectorUpdate({:?})", bitmap_idx)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -172,16 +213,23 @@ pub enum MappingKind {
|
|||
Code(CovTerm),
|
||||
/// Associates a branch region with separate counters for true and false.
|
||||
Branch { true_term: CovTerm, false_term: CovTerm },
|
||||
/// Associates a branch region with separate counters for true and false.
|
||||
MCDCBranch { true_term: CovTerm, false_term: CovTerm, mcdc_params: ConditionInfo },
|
||||
/// Associates a decision region with a bitmap and number of conditions.
|
||||
MCDCDecision(DecisionInfo),
|
||||
}
|
||||
|
||||
impl MappingKind {
|
||||
/// Iterator over all coverage terms in this mapping kind.
|
||||
pub fn terms(&self) -> impl Iterator<Item = CovTerm> {
|
||||
let one = |a| std::iter::once(a).chain(None);
|
||||
let two = |a, b| std::iter::once(a).chain(Some(b));
|
||||
let zero = || None.into_iter().chain(None);
|
||||
let one = |a| Some(a).into_iter().chain(None);
|
||||
let two = |a, b| Some(a).into_iter().chain(Some(b));
|
||||
match *self {
|
||||
Self::Code(term) => one(term),
|
||||
Self::Branch { true_term, false_term } => two(true_term, false_term),
|
||||
Self::MCDCBranch { true_term, false_term, .. } => two(true_term, false_term),
|
||||
Self::MCDCDecision(_) => zero(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -193,6 +241,12 @@ impl MappingKind {
|
|||
Self::Branch { true_term, false_term } => {
|
||||
Self::Branch { true_term: map_fn(true_term), false_term: map_fn(false_term) }
|
||||
}
|
||||
Self::MCDCBranch { true_term, false_term, mcdc_params } => Self::MCDCBranch {
|
||||
true_term: map_fn(true_term),
|
||||
false_term: map_fn(false_term),
|
||||
mcdc_params,
|
||||
},
|
||||
Self::MCDCDecision(param) => Self::MCDCDecision(param),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -212,7 +266,7 @@ pub struct Mapping {
|
|||
pub struct FunctionCoverageInfo {
|
||||
pub function_source_hash: u64,
|
||||
pub num_counters: usize,
|
||||
|
||||
pub mcdc_bitmap_bytes: u32,
|
||||
pub expressions: IndexVec<ExpressionId, Expression>,
|
||||
pub mappings: Vec<Mapping>,
|
||||
}
|
||||
|
@ -226,6 +280,8 @@ pub struct BranchInfo {
|
|||
/// data structures without having to scan the entire body first.
|
||||
pub num_block_markers: usize,
|
||||
pub branch_spans: Vec<BranchSpan>,
|
||||
pub mcdc_branch_spans: Vec<MCDCBranchSpan>,
|
||||
pub mcdc_decision_spans: Vec<MCDCDecisionSpan>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
|
@ -235,3 +291,45 @@ pub struct BranchSpan {
|
|||
pub true_marker: BlockMarkerId,
|
||||
pub false_marker: BlockMarkerId,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)]
|
||||
pub struct ConditionInfo {
|
||||
pub condition_id: ConditionId,
|
||||
pub true_next_id: ConditionId,
|
||||
pub false_next_id: ConditionId,
|
||||
}
|
||||
|
||||
impl Default for ConditionInfo {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
condition_id: ConditionId::NONE,
|
||||
true_next_id: ConditionId::NONE,
|
||||
false_next_id: ConditionId::NONE,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)]
|
||||
pub struct MCDCBranchSpan {
|
||||
pub span: Span,
|
||||
pub condition_info: ConditionInfo,
|
||||
pub true_marker: BlockMarkerId,
|
||||
pub false_marker: BlockMarkerId,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)]
|
||||
pub struct DecisionInfo {
|
||||
pub bitmap_idx: u32,
|
||||
pub conditions_num: u16,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)]
|
||||
pub struct MCDCDecisionSpan {
|
||||
pub span: Span,
|
||||
pub conditions_num: usize,
|
||||
pub end_markers: Vec<BlockMarkerId>,
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue