mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 06:44:35 +00:00
Auto merge of #126733 - ZhuUx:llvm-19-adapt, r=Zalathar
[Coverage][MCDC] Adapt mcdc to llvm 19 Related issue: #126672 Also finish task 4 at #124144 [llvm #82448](https://github.com/llvm/llvm-project/pull/82448) has introduced some break changes into mcdc, causing incompatibility between llvm 18 and 19. This draft adapts to that change and gives up supporting for llvm-18.
This commit is contained in:
commit
cf24c73141
@ -1679,16 +1679,21 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
|
|||||||
&mut self,
|
&mut self,
|
||||||
fn_name: &'ll Value,
|
fn_name: &'ll Value,
|
||||||
hash: &'ll Value,
|
hash: &'ll Value,
|
||||||
bitmap_bytes: &'ll Value,
|
bitmap_bits: &'ll Value,
|
||||||
) {
|
) {
|
||||||
debug!("mcdc_parameters() with args ({:?}, {:?}, {:?})", fn_name, hash, bitmap_bytes);
|
debug!("mcdc_parameters() with args ({:?}, {:?}, {:?})", fn_name, hash, bitmap_bits);
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
crate::llvm_util::get_version() >= (19, 0, 0),
|
||||||
|
"MCDC intrinsics require LLVM 19 or later"
|
||||||
|
);
|
||||||
|
|
||||||
let llfn = unsafe { llvm::LLVMRustGetInstrProfMCDCParametersIntrinsic(self.cx().llmod) };
|
let llfn = unsafe { llvm::LLVMRustGetInstrProfMCDCParametersIntrinsic(self.cx().llmod) };
|
||||||
let llty = self.cx.type_func(
|
let llty = self.cx.type_func(
|
||||||
&[self.cx.type_ptr(), self.cx.type_i64(), self.cx.type_i32()],
|
&[self.cx.type_ptr(), self.cx.type_i64(), self.cx.type_i32()],
|
||||||
self.cx.type_void(),
|
self.cx.type_void(),
|
||||||
);
|
);
|
||||||
let args = &[fn_name, hash, bitmap_bytes];
|
let args = &[fn_name, hash, bitmap_bits];
|
||||||
let args = self.check_call("call", llty, llfn, args);
|
let args = self.check_call("call", llty, llfn, args);
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
@ -1708,28 +1713,25 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
|
|||||||
&mut self,
|
&mut self,
|
||||||
fn_name: &'ll Value,
|
fn_name: &'ll Value,
|
||||||
hash: &'ll Value,
|
hash: &'ll Value,
|
||||||
bitmap_bytes: &'ll Value,
|
|
||||||
bitmap_index: &'ll Value,
|
bitmap_index: &'ll Value,
|
||||||
mcdc_temp: &'ll Value,
|
mcdc_temp: &'ll Value,
|
||||||
) {
|
) {
|
||||||
debug!(
|
debug!(
|
||||||
"mcdc_tvbitmap_update() with args ({:?}, {:?}, {:?}, {:?}, {:?})",
|
"mcdc_tvbitmap_update() with args ({:?}, {:?}, {:?}, {:?})",
|
||||||
fn_name, hash, bitmap_bytes, bitmap_index, mcdc_temp
|
fn_name, hash, bitmap_index, mcdc_temp
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
crate::llvm_util::get_version() >= (19, 0, 0),
|
||||||
|
"MCDC intrinsics require LLVM 19 or later"
|
||||||
);
|
);
|
||||||
|
|
||||||
let llfn =
|
let llfn =
|
||||||
unsafe { llvm::LLVMRustGetInstrProfMCDCTVBitmapUpdateIntrinsic(self.cx().llmod) };
|
unsafe { llvm::LLVMRustGetInstrProfMCDCTVBitmapUpdateIntrinsic(self.cx().llmod) };
|
||||||
let llty = self.cx.type_func(
|
let llty = self.cx.type_func(
|
||||||
&[
|
&[self.cx.type_ptr(), self.cx.type_i64(), self.cx.type_i32(), self.cx.type_ptr()],
|
||||||
self.cx.type_ptr(),
|
|
||||||
self.cx.type_i64(),
|
|
||||||
self.cx.type_i32(),
|
|
||||||
self.cx.type_i32(),
|
|
||||||
self.cx.type_ptr(),
|
|
||||||
],
|
|
||||||
self.cx.type_void(),
|
self.cx.type_void(),
|
||||||
);
|
);
|
||||||
let args = &[fn_name, hash, bitmap_bytes, bitmap_index, mcdc_temp];
|
let args = &[fn_name, hash, bitmap_index, mcdc_temp];
|
||||||
let args = self.check_call("call", llty, llfn, args);
|
let args = self.check_call("call", llty, llfn, args);
|
||||||
unsafe {
|
unsafe {
|
||||||
let _ = llvm::LLVMRustBuildCall(
|
let _ = llvm::LLVMRustBuildCall(
|
||||||
@ -1745,41 +1747,15 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
|
|||||||
self.store(self.const_i32(0), mcdc_temp, self.tcx.data_layout.i32_align.abi);
|
self.store(self.const_i32(0), mcdc_temp, self.tcx.data_layout.i32_align.abi);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn mcdc_condbitmap_update(
|
pub(crate) fn mcdc_condbitmap_update(&mut self, cond_index: &'ll Value, mcdc_temp: &'ll Value) {
|
||||||
&mut self,
|
debug!("mcdc_condbitmap_update() with args ({:?}, {:?})", cond_index, mcdc_temp);
|
||||||
fn_name: &'ll Value,
|
assert!(
|
||||||
hash: &'ll Value,
|
crate::llvm_util::get_version() >= (19, 0, 0),
|
||||||
cond_loc: &'ll Value,
|
"MCDC intrinsics require LLVM 19 or later"
|
||||||
mcdc_temp: &'ll Value,
|
|
||||||
bool_value: &'ll Value,
|
|
||||||
) {
|
|
||||||
debug!(
|
|
||||||
"mcdc_condbitmap_update() with args ({:?}, {:?}, {:?}, {:?}, {:?})",
|
|
||||||
fn_name, hash, cond_loc, mcdc_temp, bool_value
|
|
||||||
);
|
);
|
||||||
let llfn = unsafe { llvm::LLVMRustGetInstrProfMCDCCondBitmapIntrinsic(self.cx().llmod) };
|
let align = self.tcx.data_layout.i32_align.abi;
|
||||||
let llty = self.cx.type_func(
|
let current_tv_index = self.load(self.cx.type_i32(), mcdc_temp, align);
|
||||||
&[
|
let new_tv_index = self.add(current_tv_index, cond_index);
|
||||||
self.cx.type_ptr(),
|
self.store(new_tv_index, mcdc_temp, align);
|
||||||
self.cx.type_i64(),
|
|
||||||
self.cx.type_i32(),
|
|
||||||
self.cx.type_ptr(),
|
|
||||||
self.cx.type_i1(),
|
|
||||||
],
|
|
||||||
self.cx.type_void(),
|
|
||||||
);
|
|
||||||
let args = &[fn_name, hash, cond_loc, mcdc_temp, bool_value];
|
|
||||||
self.check_call("call", llty, llfn, args);
|
|
||||||
unsafe {
|
|
||||||
let _ = llvm::LLVMRustBuildCall(
|
|
||||||
self.llbuilder,
|
|
||||||
llty,
|
|
||||||
llfn,
|
|
||||||
args.as_ptr() as *const &llvm::Value,
|
|
||||||
args.len() as c_uint,
|
|
||||||
[].as_ptr(),
|
|
||||||
0 as c_uint,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -111,7 +111,7 @@ enum RegionKind {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mod mcdc {
|
mod mcdc {
|
||||||
use rustc_middle::mir::coverage::{ConditionInfo, DecisionInfo};
|
use rustc_middle::mir::coverage::{ConditionId, ConditionInfo, DecisionInfo};
|
||||||
|
|
||||||
/// Must match the layout of `LLVMRustMCDCDecisionParameters`.
|
/// Must match the layout of `LLVMRustMCDCDecisionParameters`.
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
@ -167,12 +167,13 @@ mod mcdc {
|
|||||||
|
|
||||||
impl From<ConditionInfo> for BranchParameters {
|
impl From<ConditionInfo> for BranchParameters {
|
||||||
fn from(value: ConditionInfo) -> Self {
|
fn from(value: ConditionInfo) -> Self {
|
||||||
|
let to_llvm_cond_id = |cond_id: Option<ConditionId>| {
|
||||||
|
cond_id.and_then(|id| LLVMConditionId::try_from(id.as_usize()).ok()).unwrap_or(-1)
|
||||||
|
};
|
||||||
|
let ConditionInfo { condition_id, true_next_id, false_next_id } = value;
|
||||||
Self {
|
Self {
|
||||||
condition_id: value.condition_id.as_u32() as LLVMConditionId,
|
condition_id: to_llvm_cond_id(Some(condition_id)),
|
||||||
condition_ids: [
|
condition_ids: [to_llvm_cond_id(false_next_id), to_llvm_cond_id(true_next_id)],
|
||||||
value.false_next_id.as_u32() as LLVMConditionId,
|
|
||||||
value.true_next_id.as_u32() as LLVMConditionId,
|
|
||||||
],
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -98,14 +98,14 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// If there are no MC/DC bitmaps to set up, return immediately.
|
// If there are no MC/DC bitmaps to set up, return immediately.
|
||||||
if function_coverage_info.mcdc_bitmap_bytes == 0 {
|
if function_coverage_info.mcdc_bitmap_bits == 0 {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let fn_name = self.get_pgo_func_name_var(instance);
|
let fn_name = self.get_pgo_func_name_var(instance);
|
||||||
let hash = self.const_u64(function_coverage_info.function_source_hash);
|
let hash = self.const_u64(function_coverage_info.function_source_hash);
|
||||||
let bitmap_bytes = self.const_u32(function_coverage_info.mcdc_bitmap_bytes);
|
let bitmap_bits = self.const_u32(function_coverage_info.mcdc_bitmap_bits as u32);
|
||||||
self.mcdc_parameters(fn_name, hash, bitmap_bytes);
|
self.mcdc_parameters(fn_name, hash, bitmap_bits);
|
||||||
|
|
||||||
// Create pointers named `mcdc.addr.{i}` to stack-allocated condition bitmaps.
|
// Create pointers named `mcdc.addr.{i}` to stack-allocated condition bitmaps.
|
||||||
let mut cond_bitmaps = vec![];
|
let mut cond_bitmaps = vec![];
|
||||||
@ -185,35 +185,28 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> {
|
|||||||
CoverageKind::ExpressionUsed { id } => {
|
CoverageKind::ExpressionUsed { id } => {
|
||||||
func_coverage.mark_expression_id_seen(id);
|
func_coverage.mark_expression_id_seen(id);
|
||||||
}
|
}
|
||||||
CoverageKind::CondBitmapUpdate { id, value, decision_depth } => {
|
CoverageKind::CondBitmapUpdate { index, decision_depth } => {
|
||||||
drop(coverage_map);
|
drop(coverage_map);
|
||||||
assert_ne!(
|
|
||||||
id.as_u32(),
|
|
||||||
0,
|
|
||||||
"ConditionId of evaluated conditions should never be zero"
|
|
||||||
);
|
|
||||||
let cond_bitmap = coverage_context
|
let cond_bitmap = coverage_context
|
||||||
.try_get_mcdc_condition_bitmap(&instance, decision_depth)
|
.try_get_mcdc_condition_bitmap(&instance, decision_depth)
|
||||||
.expect("mcdc cond bitmap should have been allocated for updating");
|
.expect("mcdc cond bitmap should have been allocated for updating");
|
||||||
let cond_loc = bx.const_i32(id.as_u32() as i32 - 1);
|
let cond_index = bx.const_i32(index as i32);
|
||||||
let bool_value = bx.const_bool(value);
|
bx.mcdc_condbitmap_update(cond_index, cond_bitmap);
|
||||||
let fn_name = bx.get_pgo_func_name_var(instance);
|
|
||||||
let hash = bx.const_u64(function_coverage_info.function_source_hash);
|
|
||||||
bx.mcdc_condbitmap_update(fn_name, hash, cond_loc, cond_bitmap, bool_value);
|
|
||||||
}
|
}
|
||||||
CoverageKind::TestVectorBitmapUpdate { bitmap_idx, decision_depth } => {
|
CoverageKind::TestVectorBitmapUpdate { bitmap_idx, decision_depth } => {
|
||||||
drop(coverage_map);
|
drop(coverage_map);
|
||||||
let cond_bitmap = coverage_context
|
let cond_bitmap = coverage_context
|
||||||
.try_get_mcdc_condition_bitmap(&instance, decision_depth)
|
.try_get_mcdc_condition_bitmap(&instance, decision_depth)
|
||||||
.expect("mcdc cond bitmap should have been allocated for merging into the global bitmap");
|
.expect("mcdc cond bitmap should have been allocated for merging into the global bitmap");
|
||||||
let bitmap_bytes = function_coverage_info.mcdc_bitmap_bytes;
|
assert!(
|
||||||
assert!(bitmap_idx < bitmap_bytes, "bitmap index of the decision out of range");
|
bitmap_idx as usize <= function_coverage_info.mcdc_bitmap_bits,
|
||||||
|
"bitmap index of the decision out of range"
|
||||||
|
);
|
||||||
|
|
||||||
let fn_name = bx.get_pgo_func_name_var(instance);
|
let fn_name = bx.get_pgo_func_name_var(instance);
|
||||||
let hash = bx.const_u64(function_coverage_info.function_source_hash);
|
let hash = bx.const_u64(function_coverage_info.function_source_hash);
|
||||||
let bitmap_bytes = bx.const_u32(bitmap_bytes);
|
|
||||||
let bitmap_index = bx.const_u32(bitmap_idx);
|
let bitmap_index = bx.const_u32(bitmap_idx);
|
||||||
bx.mcdc_tvbitmap_update(fn_name, hash, bitmap_bytes, bitmap_index, cond_bitmap);
|
bx.mcdc_tvbitmap_update(fn_name, hash, bitmap_index, cond_bitmap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1614,7 +1614,6 @@ unsafe extern "C" {
|
|||||||
pub fn LLVMRustGetInstrProfIncrementIntrinsic(M: &Module) -> &Value;
|
pub fn LLVMRustGetInstrProfIncrementIntrinsic(M: &Module) -> &Value;
|
||||||
pub fn LLVMRustGetInstrProfMCDCParametersIntrinsic(M: &Module) -> &Value;
|
pub fn LLVMRustGetInstrProfMCDCParametersIntrinsic(M: &Module) -> &Value;
|
||||||
pub fn LLVMRustGetInstrProfMCDCTVBitmapUpdateIntrinsic(M: &Module) -> &Value;
|
pub fn LLVMRustGetInstrProfMCDCTVBitmapUpdateIntrinsic(M: &Module) -> &Value;
|
||||||
pub fn LLVMRustGetInstrProfMCDCCondBitmapIntrinsic(M: &Module) -> &Value;
|
|
||||||
|
|
||||||
pub fn LLVMRustBuildCall<'a>(
|
pub fn LLVMRustBuildCall<'a>(
|
||||||
B: &Builder<'a>,
|
B: &Builder<'a>,
|
||||||
|
@ -88,38 +88,7 @@ struct LLVMRustMCDCParameters {
|
|||||||
LLVMRustMCDCBranchParameters BranchParameters;
|
LLVMRustMCDCBranchParameters BranchParameters;
|
||||||
};
|
};
|
||||||
|
|
||||||
// LLVM representations for `MCDCParameters` evolved from LLVM 18 to 19.
|
#if LLVM_VERSION_GE(19, 0)
|
||||||
// Look at representations in 18
|
|
||||||
// https://github.com/rust-lang/llvm-project/blob/66a2881a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L253-L263
|
|
||||||
// and representations in 19
|
|
||||||
// https://github.com/llvm/llvm-project/blob/843cc474faefad1d639f4c44c1cf3ad7dbda76c8/llvm/include/llvm/ProfileData/Coverage/MCDCTypes.h
|
|
||||||
#if LLVM_VERSION_LT(19, 0)
|
|
||||||
static coverage::CounterMappingRegion::MCDCParameters
|
|
||||||
fromRust(LLVMRustMCDCParameters Params) {
|
|
||||||
auto parameter = coverage::CounterMappingRegion::MCDCParameters{};
|
|
||||||
switch (Params.Tag) {
|
|
||||||
case LLVMRustMCDCParametersTag::None:
|
|
||||||
return parameter;
|
|
||||||
case LLVMRustMCDCParametersTag::Decision:
|
|
||||||
parameter.BitmapIdx =
|
|
||||||
static_cast<unsigned>(Params.DecisionParameters.BitmapIdx),
|
|
||||||
parameter.NumConditions =
|
|
||||||
static_cast<unsigned>(Params.DecisionParameters.NumConditions);
|
|
||||||
return parameter;
|
|
||||||
case LLVMRustMCDCParametersTag::Branch:
|
|
||||||
parameter.ID = static_cast<coverage::CounterMappingRegion::MCDCConditionID>(
|
|
||||||
Params.BranchParameters.ConditionID),
|
|
||||||
parameter.FalseID =
|
|
||||||
static_cast<coverage::CounterMappingRegion::MCDCConditionID>(
|
|
||||||
Params.BranchParameters.ConditionIDs[0]),
|
|
||||||
parameter.TrueID =
|
|
||||||
static_cast<coverage::CounterMappingRegion::MCDCConditionID>(
|
|
||||||
Params.BranchParameters.ConditionIDs[1]);
|
|
||||||
return parameter;
|
|
||||||
}
|
|
||||||
report_fatal_error("Bad LLVMRustMCDCParametersTag!");
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
static coverage::mcdc::Parameters fromRust(LLVMRustMCDCParameters Params) {
|
static coverage::mcdc::Parameters fromRust(LLVMRustMCDCParameters Params) {
|
||||||
switch (Params.Tag) {
|
switch (Params.Tag) {
|
||||||
case LLVMRustMCDCParametersTag::None:
|
case LLVMRustMCDCParametersTag::None:
|
||||||
@ -214,13 +183,17 @@ extern "C" void LLVMRustCoverageWriteMappingToBuffer(
|
|||||||
RustMappingRegions, NumMappingRegions)) {
|
RustMappingRegions, NumMappingRegions)) {
|
||||||
MappingRegions.emplace_back(
|
MappingRegions.emplace_back(
|
||||||
fromRust(Region.Count), fromRust(Region.FalseCount),
|
fromRust(Region.Count), fromRust(Region.FalseCount),
|
||||||
#if LLVM_VERSION_LT(19, 0)
|
#if LLVM_VERSION_GE(18, 0) && LLVM_VERSION_LT(19, 0)
|
||||||
// LLVM 19 may move this argument to last.
|
coverage::CounterMappingRegion::MCDCParameters{},
|
||||||
fromRust(Region.MCDCParameters),
|
|
||||||
#endif
|
#endif
|
||||||
Region.FileID, Region.ExpandedFileID, // File IDs, then region info.
|
Region.FileID, Region.ExpandedFileID, // File IDs, then region info.
|
||||||
Region.LineStart, Region.ColumnStart, Region.LineEnd, Region.ColumnEnd,
|
Region.LineStart, Region.ColumnStart, Region.LineEnd, Region.ColumnEnd,
|
||||||
fromRust(Region.Kind));
|
fromRust(Region.Kind)
|
||||||
|
#if LLVM_VERSION_GE(19, 0)
|
||||||
|
,
|
||||||
|
fromRust(Region.MCDCParameters)
|
||||||
|
#endif
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<coverage::CounterExpression> Expressions;
|
std::vector<coverage::CounterExpression> Expressions;
|
||||||
|
@ -1539,23 +1539,21 @@ LLVMRustGetInstrProfIncrementIntrinsic(LLVMModuleRef M) {
|
|||||||
|
|
||||||
extern "C" LLVMValueRef
|
extern "C" LLVMValueRef
|
||||||
LLVMRustGetInstrProfMCDCParametersIntrinsic(LLVMModuleRef M) {
|
LLVMRustGetInstrProfMCDCParametersIntrinsic(LLVMModuleRef M) {
|
||||||
|
#if LLVM_VERSION_GE(19, 0)
|
||||||
return wrap(llvm::Intrinsic::getDeclaration(
|
return wrap(llvm::Intrinsic::getDeclaration(
|
||||||
unwrap(M), llvm::Intrinsic::instrprof_mcdc_parameters));
|
unwrap(M), llvm::Intrinsic::instrprof_mcdc_parameters));
|
||||||
|
#else
|
||||||
|
report_fatal_error("LLVM 19.0 is required for mcdc intrinsic functions");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" LLVMValueRef
|
extern "C" LLVMValueRef
|
||||||
LLVMRustGetInstrProfMCDCTVBitmapUpdateIntrinsic(LLVMModuleRef M) {
|
LLVMRustGetInstrProfMCDCTVBitmapUpdateIntrinsic(LLVMModuleRef M) {
|
||||||
|
#if LLVM_VERSION_GE(19, 0)
|
||||||
return wrap(llvm::Intrinsic::getDeclaration(
|
return wrap(llvm::Intrinsic::getDeclaration(
|
||||||
unwrap(M), llvm::Intrinsic::instrprof_mcdc_tvbitmap_update));
|
unwrap(M), llvm::Intrinsic::instrprof_mcdc_tvbitmap_update));
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" LLVMValueRef
|
|
||||||
LLVMRustGetInstrProfMCDCCondBitmapIntrinsic(LLVMModuleRef M) {
|
|
||||||
#if LLVM_VERSION_LT(19, 0)
|
|
||||||
return wrap(llvm::Intrinsic::getDeclaration(
|
|
||||||
unwrap(M), llvm::Intrinsic::instrprof_mcdc_condbitmap_update));
|
|
||||||
#else
|
#else
|
||||||
report_fatal_error("LLVM 18.0 is required for mcdc intrinsic functions");
|
report_fatal_error("LLVM 19.0 is required for mcdc intrinsic functions");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,7 +67,7 @@ rustc_index::newtype_index! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ConditionId {
|
impl ConditionId {
|
||||||
pub const NONE: Self = Self::from_u32(0);
|
pub const START: Self = Self::from_usize(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Enum that can hold a constant zero value, the ID of an physical coverage
|
/// Enum that can hold a constant zero value, the ID of an physical coverage
|
||||||
@ -128,8 +128,8 @@ pub enum CoverageKind {
|
|||||||
|
|
||||||
/// Marks the point in MIR control flow represented by a evaluated condition.
|
/// 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.
|
/// This is eventually lowered to instruments updating mcdc temp variables.
|
||||||
CondBitmapUpdate { id: ConditionId, value: bool, decision_depth: u16 },
|
CondBitmapUpdate { index: u32, decision_depth: u16 },
|
||||||
|
|
||||||
/// Marks the point in MIR control flow represented by a evaluated decision.
|
/// Marks the point in MIR control flow represented by a evaluated decision.
|
||||||
///
|
///
|
||||||
@ -145,14 +145,8 @@ impl Debug for CoverageKind {
|
|||||||
BlockMarker { id } => write!(fmt, "BlockMarker({:?})", id.index()),
|
BlockMarker { id } => write!(fmt, "BlockMarker({:?})", id.index()),
|
||||||
CounterIncrement { id } => write!(fmt, "CounterIncrement({:?})", id.index()),
|
CounterIncrement { id } => write!(fmt, "CounterIncrement({:?})", id.index()),
|
||||||
ExpressionUsed { id } => write!(fmt, "ExpressionUsed({:?})", id.index()),
|
ExpressionUsed { id } => write!(fmt, "ExpressionUsed({:?})", id.index()),
|
||||||
CondBitmapUpdate { id, value, decision_depth } => {
|
CondBitmapUpdate { index, decision_depth } => {
|
||||||
write!(
|
write!(fmt, "CondBitmapUpdate(index={:?}, depth={:?})", index, decision_depth)
|
||||||
fmt,
|
|
||||||
"CondBitmapUpdate({:?}, {:?}, depth={:?})",
|
|
||||||
id.index(),
|
|
||||||
value,
|
|
||||||
decision_depth
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
TestVectorBitmapUpdate { bitmap_idx, decision_depth } => {
|
TestVectorBitmapUpdate { bitmap_idx, decision_depth } => {
|
||||||
write!(fmt, "TestVectorUpdate({:?}, depth={:?})", bitmap_idx, decision_depth)
|
write!(fmt, "TestVectorUpdate({:?}, depth={:?})", bitmap_idx, decision_depth)
|
||||||
@ -253,7 +247,7 @@ pub struct Mapping {
|
|||||||
pub struct FunctionCoverageInfo {
|
pub struct FunctionCoverageInfo {
|
||||||
pub function_source_hash: u64,
|
pub function_source_hash: u64,
|
||||||
pub num_counters: usize,
|
pub num_counters: usize,
|
||||||
pub mcdc_bitmap_bytes: u32,
|
pub mcdc_bitmap_bits: usize,
|
||||||
pub expressions: IndexVec<ExpressionId, Expression>,
|
pub expressions: IndexVec<ExpressionId, Expression>,
|
||||||
pub mappings: Vec<Mapping>,
|
pub mappings: Vec<Mapping>,
|
||||||
/// The depth of the deepest decision is used to know how many
|
/// The depth of the deepest decision is used to know how many
|
||||||
@ -275,8 +269,10 @@ pub struct CoverageInfoHi {
|
|||||||
/// data structures without having to scan the entire body first.
|
/// data structures without having to scan the entire body first.
|
||||||
pub num_block_markers: usize,
|
pub num_block_markers: usize,
|
||||||
pub branch_spans: Vec<BranchSpan>,
|
pub branch_spans: Vec<BranchSpan>,
|
||||||
pub mcdc_branch_spans: Vec<MCDCBranchSpan>,
|
/// Branch spans generated by mcdc. Because of some limits mcdc builder give up generating
|
||||||
pub mcdc_decision_spans: Vec<MCDCDecisionSpan>,
|
/// decisions including them so that they are handled as normal branch spans.
|
||||||
|
pub mcdc_degraded_branch_spans: Vec<MCDCBranchSpan>,
|
||||||
|
pub mcdc_spans: Vec<(MCDCDecisionSpan, Vec<MCDCBranchSpan>)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
@ -291,30 +287,17 @@ pub struct BranchSpan {
|
|||||||
#[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)]
|
#[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)]
|
||||||
pub struct ConditionInfo {
|
pub struct ConditionInfo {
|
||||||
pub condition_id: ConditionId,
|
pub condition_id: ConditionId,
|
||||||
pub true_next_id: ConditionId,
|
pub true_next_id: Option<ConditionId>,
|
||||||
pub false_next_id: ConditionId,
|
pub false_next_id: Option<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(Clone, Debug)]
|
||||||
#[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)]
|
#[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)]
|
||||||
pub struct MCDCBranchSpan {
|
pub struct MCDCBranchSpan {
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
/// If `None`, this actually represents a normal branch span inserted for
|
pub condition_info: ConditionInfo,
|
||||||
/// code that was too complex for MC/DC.
|
|
||||||
pub condition_info: Option<ConditionInfo>,
|
|
||||||
pub true_marker: BlockMarkerId,
|
pub true_marker: BlockMarkerId,
|
||||||
pub false_marker: BlockMarkerId,
|
pub false_marker: BlockMarkerId,
|
||||||
pub decision_depth: u16,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
@ -328,7 +311,7 @@ pub struct DecisionInfo {
|
|||||||
#[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)]
|
#[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)]
|
||||||
pub struct MCDCDecisionSpan {
|
pub struct MCDCDecisionSpan {
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
pub num_conditions: usize,
|
|
||||||
pub end_markers: Vec<BlockMarkerId>,
|
pub end_markers: Vec<BlockMarkerId>,
|
||||||
pub decision_depth: u16,
|
pub decision_depth: u16,
|
||||||
|
pub num_conditions: usize,
|
||||||
}
|
}
|
||||||
|
@ -538,8 +538,8 @@ fn write_coverage_info_hi(
|
|||||||
let coverage::CoverageInfoHi {
|
let coverage::CoverageInfoHi {
|
||||||
num_block_markers: _,
|
num_block_markers: _,
|
||||||
branch_spans,
|
branch_spans,
|
||||||
mcdc_branch_spans,
|
mcdc_degraded_branch_spans,
|
||||||
mcdc_decision_spans,
|
mcdc_spans,
|
||||||
} = coverage_info_hi;
|
} = coverage_info_hi;
|
||||||
|
|
||||||
// Only add an extra trailing newline if we printed at least one thing.
|
// Only add an extra trailing newline if we printed at least one thing.
|
||||||
@ -553,29 +553,35 @@ fn write_coverage_info_hi(
|
|||||||
did_print = true;
|
did_print = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
for coverage::MCDCBranchSpan {
|
for coverage::MCDCBranchSpan { span, true_marker, false_marker, .. } in
|
||||||
span,
|
mcdc_degraded_branch_spans
|
||||||
condition_info,
|
|
||||||
true_marker,
|
|
||||||
false_marker,
|
|
||||||
decision_depth,
|
|
||||||
} in mcdc_branch_spans
|
|
||||||
{
|
{
|
||||||
writeln!(
|
writeln!(
|
||||||
w,
|
w,
|
||||||
"{INDENT}coverage mcdc branch {{ condition_id: {:?}, true: {true_marker:?}, false: {false_marker:?}, depth: {decision_depth:?} }} => {span:?}",
|
"{INDENT}coverage branch {{ true: {true_marker:?}, false: {false_marker:?} }} => {span:?}",
|
||||||
condition_info.map(|info| info.condition_id)
|
|
||||||
)?;
|
)?;
|
||||||
did_print = true;
|
did_print = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
for coverage::MCDCDecisionSpan { span, num_conditions, end_markers, decision_depth } in
|
for (
|
||||||
mcdc_decision_spans
|
coverage::MCDCDecisionSpan { span, end_markers, decision_depth, num_conditions: _ },
|
||||||
|
conditions,
|
||||||
|
) in mcdc_spans
|
||||||
{
|
{
|
||||||
|
let num_conditions = conditions.len();
|
||||||
writeln!(
|
writeln!(
|
||||||
w,
|
w,
|
||||||
"{INDENT}coverage mcdc decision {{ num_conditions: {num_conditions:?}, end: {end_markers:?}, depth: {decision_depth:?} }} => {span:?}"
|
"{INDENT}coverage mcdc decision {{ num_conditions: {num_conditions:?}, end: {end_markers:?}, depth: {decision_depth:?} }} => {span:?}"
|
||||||
)?;
|
)?;
|
||||||
|
for coverage::MCDCBranchSpan { span, condition_info, true_marker, false_marker } in
|
||||||
|
conditions
|
||||||
|
{
|
||||||
|
writeln!(
|
||||||
|
w,
|
||||||
|
"{INDENT}coverage mcdc branch {{ condition_id: {:?}, true: {true_marker:?}, false: {false_marker:?} }} => {span:?}",
|
||||||
|
condition_info.condition_id
|
||||||
|
)?;
|
||||||
|
}
|
||||||
did_print = true;
|
did_print = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,7 +175,7 @@ impl CoverageInfoBuilder {
|
|||||||
let branch_spans =
|
let branch_spans =
|
||||||
branch_info.map(|branch_info| branch_info.branch_spans).unwrap_or_default();
|
branch_info.map(|branch_info| branch_info.branch_spans).unwrap_or_default();
|
||||||
|
|
||||||
let (mcdc_decision_spans, mcdc_branch_spans) =
|
let (mcdc_spans, mcdc_degraded_branch_spans) =
|
||||||
mcdc_info.map(MCDCInfoBuilder::into_done).unwrap_or_default();
|
mcdc_info.map(MCDCInfoBuilder::into_done).unwrap_or_default();
|
||||||
|
|
||||||
// For simplicity, always return an info struct (without Option), even
|
// For simplicity, always return an info struct (without Option), even
|
||||||
@ -183,8 +183,8 @@ impl CoverageInfoBuilder {
|
|||||||
Box::new(CoverageInfoHi {
|
Box::new(CoverageInfoHi {
|
||||||
num_block_markers,
|
num_block_markers,
|
||||||
branch_spans,
|
branch_spans,
|
||||||
mcdc_branch_spans,
|
mcdc_degraded_branch_spans,
|
||||||
mcdc_decision_spans,
|
mcdc_spans,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,16 +12,16 @@ use rustc_span::Span;
|
|||||||
use crate::build::Builder;
|
use crate::build::Builder;
|
||||||
use crate::errors::MCDCExceedsConditionLimit;
|
use crate::errors::MCDCExceedsConditionLimit;
|
||||||
|
|
||||||
/// The MCDC bitmap scales exponentially (2^n) based on the number of conditions seen,
|
/// LLVM uses `i16` to represent condition id. Hence `i16::MAX` is the hard limit for number of
|
||||||
/// So llvm sets a maximum value prevents the bitmap footprint from growing too large without the user's knowledge.
|
/// conditions in a decision.
|
||||||
/// This limit may be relaxed if the [upstream change](https://github.com/llvm/llvm-project/pull/82448) is merged.
|
const MAX_CONDITIONS_IN_DECISION: usize = i16::MAX as usize;
|
||||||
const MAX_CONDITIONS_IN_DECISION: usize = 6;
|
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct MCDCDecisionCtx {
|
struct MCDCDecisionCtx {
|
||||||
/// To construct condition evaluation tree.
|
/// To construct condition evaluation tree.
|
||||||
decision_stack: VecDeque<ConditionInfo>,
|
decision_stack: VecDeque<ConditionInfo>,
|
||||||
processing_decision: Option<MCDCDecisionSpan>,
|
processing_decision: Option<MCDCDecisionSpan>,
|
||||||
|
conditions: Vec<MCDCBranchSpan>,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct MCDCState {
|
struct MCDCState {
|
||||||
@ -106,22 +106,27 @@ impl MCDCState {
|
|||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
|
|
||||||
let parent_condition = decision_ctx.decision_stack.pop_back().unwrap_or_default();
|
let parent_condition = decision_ctx.decision_stack.pop_back().unwrap_or_else(|| {
|
||||||
let lhs_id = if parent_condition.condition_id == ConditionId::NONE {
|
assert_eq!(
|
||||||
|
decision.num_conditions, 0,
|
||||||
|
"decision stack must be empty only for empty decision"
|
||||||
|
);
|
||||||
decision.num_conditions += 1;
|
decision.num_conditions += 1;
|
||||||
ConditionId::from(decision.num_conditions)
|
ConditionInfo {
|
||||||
} else {
|
condition_id: ConditionId::START,
|
||||||
parent_condition.condition_id
|
true_next_id: None,
|
||||||
};
|
false_next_id: None,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
let lhs_id = parent_condition.condition_id;
|
||||||
|
|
||||||
decision.num_conditions += 1;
|
|
||||||
let rhs_condition_id = ConditionId::from(decision.num_conditions);
|
let rhs_condition_id = ConditionId::from(decision.num_conditions);
|
||||||
|
decision.num_conditions += 1;
|
||||||
let (lhs, rhs) = match op {
|
let (lhs, rhs) = match op {
|
||||||
LogicalOp::And => {
|
LogicalOp::And => {
|
||||||
let lhs = ConditionInfo {
|
let lhs = ConditionInfo {
|
||||||
condition_id: lhs_id,
|
condition_id: lhs_id,
|
||||||
true_next_id: rhs_condition_id,
|
true_next_id: Some(rhs_condition_id),
|
||||||
false_next_id: parent_condition.false_next_id,
|
false_next_id: parent_condition.false_next_id,
|
||||||
};
|
};
|
||||||
let rhs = ConditionInfo {
|
let rhs = ConditionInfo {
|
||||||
@ -135,7 +140,7 @@ impl MCDCState {
|
|||||||
let lhs = ConditionInfo {
|
let lhs = ConditionInfo {
|
||||||
condition_id: lhs_id,
|
condition_id: lhs_id,
|
||||||
true_next_id: parent_condition.true_next_id,
|
true_next_id: parent_condition.true_next_id,
|
||||||
false_next_id: rhs_condition_id,
|
false_next_id: Some(rhs_condition_id),
|
||||||
};
|
};
|
||||||
let rhs = ConditionInfo {
|
let rhs = ConditionInfo {
|
||||||
condition_id: rhs_condition_id,
|
condition_id: rhs_condition_id,
|
||||||
@ -150,44 +155,64 @@ impl MCDCState {
|
|||||||
decision_ctx.decision_stack.push_back(lhs);
|
decision_ctx.decision_stack.push_back(lhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn take_condition(
|
fn try_finish_decision(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
span: Span,
|
||||||
true_marker: BlockMarkerId,
|
true_marker: BlockMarkerId,
|
||||||
false_marker: BlockMarkerId,
|
false_marker: BlockMarkerId,
|
||||||
) -> (Option<ConditionInfo>, Option<MCDCDecisionSpan>) {
|
degraded_branches: &mut Vec<MCDCBranchSpan>,
|
||||||
|
) -> Option<(MCDCDecisionSpan, Vec<MCDCBranchSpan>)> {
|
||||||
let Some(decision_ctx) = self.decision_ctx_stack.last_mut() else {
|
let Some(decision_ctx) = self.decision_ctx_stack.last_mut() else {
|
||||||
bug!("Unexpected empty decision_ctx_stack")
|
bug!("Unexpected empty decision_ctx_stack")
|
||||||
};
|
};
|
||||||
let Some(condition_info) = decision_ctx.decision_stack.pop_back() else {
|
let Some(condition_info) = decision_ctx.decision_stack.pop_back() else {
|
||||||
return (None, None);
|
let branch = MCDCBranchSpan {
|
||||||
|
span,
|
||||||
|
condition_info: ConditionInfo {
|
||||||
|
condition_id: ConditionId::START,
|
||||||
|
true_next_id: None,
|
||||||
|
false_next_id: None,
|
||||||
|
},
|
||||||
|
true_marker,
|
||||||
|
false_marker,
|
||||||
|
};
|
||||||
|
degraded_branches.push(branch);
|
||||||
|
return None;
|
||||||
};
|
};
|
||||||
let Some(decision) = decision_ctx.processing_decision.as_mut() else {
|
let Some(decision) = decision_ctx.processing_decision.as_mut() else {
|
||||||
bug!("Processing decision should have been created before any conditions are taken");
|
bug!("Processing decision should have been created before any conditions are taken");
|
||||||
};
|
};
|
||||||
if condition_info.true_next_id == ConditionId::NONE {
|
if condition_info.true_next_id.is_none() {
|
||||||
decision.end_markers.push(true_marker);
|
decision.end_markers.push(true_marker);
|
||||||
}
|
}
|
||||||
if condition_info.false_next_id == ConditionId::NONE {
|
if condition_info.false_next_id.is_none() {
|
||||||
decision.end_markers.push(false_marker);
|
decision.end_markers.push(false_marker);
|
||||||
}
|
}
|
||||||
|
decision_ctx.conditions.push(MCDCBranchSpan {
|
||||||
|
span,
|
||||||
|
condition_info,
|
||||||
|
true_marker,
|
||||||
|
false_marker,
|
||||||
|
});
|
||||||
|
|
||||||
if decision_ctx.decision_stack.is_empty() {
|
if decision_ctx.decision_stack.is_empty() {
|
||||||
(Some(condition_info), decision_ctx.processing_decision.take())
|
let conditions = std::mem::take(&mut decision_ctx.conditions);
|
||||||
|
decision_ctx.processing_decision.take().map(|decision| (decision, conditions))
|
||||||
} else {
|
} else {
|
||||||
(Some(condition_info), None)
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) struct MCDCInfoBuilder {
|
pub(crate) struct MCDCInfoBuilder {
|
||||||
branch_spans: Vec<MCDCBranchSpan>,
|
degraded_spans: Vec<MCDCBranchSpan>,
|
||||||
decision_spans: Vec<MCDCDecisionSpan>,
|
mcdc_spans: Vec<(MCDCDecisionSpan, Vec<MCDCBranchSpan>)>,
|
||||||
state: MCDCState,
|
state: MCDCState,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MCDCInfoBuilder {
|
impl MCDCInfoBuilder {
|
||||||
pub(crate) fn new() -> Self {
|
pub(crate) fn new() -> Self {
|
||||||
Self { branch_spans: vec![], decision_spans: vec![], state: MCDCState::new() }
|
Self { degraded_spans: vec![], mcdc_spans: vec![], state: MCDCState::new() }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn visit_evaluated_condition(
|
pub(crate) fn visit_evaluated_condition(
|
||||||
@ -201,50 +226,44 @@ impl MCDCInfoBuilder {
|
|||||||
let true_marker = inject_block_marker(source_info, true_block);
|
let true_marker = inject_block_marker(source_info, true_block);
|
||||||
let false_marker = inject_block_marker(source_info, false_block);
|
let false_marker = inject_block_marker(source_info, false_block);
|
||||||
|
|
||||||
let decision_depth = self.state.decision_depth();
|
|
||||||
let (mut condition_info, decision_result) =
|
|
||||||
self.state.take_condition(true_marker, false_marker);
|
|
||||||
// take_condition() returns Some for decision_result when the decision stack
|
// take_condition() returns Some for decision_result when the decision stack
|
||||||
// is empty, i.e. when all the conditions of the decision were instrumented,
|
// is empty, i.e. when all the conditions of the decision were instrumented,
|
||||||
// and the decision is "complete".
|
// and the decision is "complete".
|
||||||
if let Some(decision) = decision_result {
|
if let Some((decision, conditions)) = self.state.try_finish_decision(
|
||||||
match decision.num_conditions {
|
source_info.span,
|
||||||
|
true_marker,
|
||||||
|
false_marker,
|
||||||
|
&mut self.degraded_spans,
|
||||||
|
) {
|
||||||
|
let num_conditions = conditions.len();
|
||||||
|
assert_eq!(
|
||||||
|
num_conditions, decision.num_conditions,
|
||||||
|
"final number of conditions is not correct"
|
||||||
|
);
|
||||||
|
match num_conditions {
|
||||||
0 => {
|
0 => {
|
||||||
unreachable!("Decision with no condition is not expected");
|
unreachable!("Decision with no condition is not expected");
|
||||||
}
|
}
|
||||||
1..=MAX_CONDITIONS_IN_DECISION => {
|
1..=MAX_CONDITIONS_IN_DECISION => {
|
||||||
self.decision_spans.push(decision);
|
self.mcdc_spans.push((decision, conditions));
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
// Do not generate mcdc mappings and statements for decisions with too many conditions.
|
self.degraded_spans.extend(conditions);
|
||||||
// Therefore, first erase the condition info of the (N-1) previous branch spans.
|
|
||||||
let rebase_idx = self.branch_spans.len() - (decision.num_conditions - 1);
|
|
||||||
for branch in &mut self.branch_spans[rebase_idx..] {
|
|
||||||
branch.condition_info = None;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Then, erase this last branch span's info too, for a total of N.
|
|
||||||
condition_info = None;
|
|
||||||
|
|
||||||
tcx.dcx().emit_warn(MCDCExceedsConditionLimit {
|
tcx.dcx().emit_warn(MCDCExceedsConditionLimit {
|
||||||
span: decision.span,
|
span: decision.span,
|
||||||
num_conditions: decision.num_conditions,
|
num_conditions,
|
||||||
max_conditions: MAX_CONDITIONS_IN_DECISION,
|
max_conditions: MAX_CONDITIONS_IN_DECISION,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.branch_spans.push(MCDCBranchSpan {
|
|
||||||
span: source_info.span,
|
|
||||||
condition_info,
|
|
||||||
true_marker,
|
|
||||||
false_marker,
|
|
||||||
decision_depth,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn into_done(self) -> (Vec<MCDCDecisionSpan>, Vec<MCDCBranchSpan>) {
|
pub(crate) fn into_done(
|
||||||
(self.decision_spans, self.branch_spans)
|
self,
|
||||||
|
) -> (Vec<(MCDCDecisionSpan, Vec<MCDCBranchSpan>)>, Vec<MCDCBranchSpan>) {
|
||||||
|
(self.mcdc_spans, self.degraded_spans)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,6 +9,8 @@ mir_transform_const_mut_borrow = taking a mutable reference to a `const` item
|
|||||||
.note2 = the mutable reference will refer to this temporary, not the original `const` item
|
.note2 = the mutable reference will refer to this temporary, not the original `const` item
|
||||||
.note3 = mutable reference created due to call to this method
|
.note3 = mutable reference created due to call to this method
|
||||||
|
|
||||||
|
mir_transform_exceeds_mcdc_test_vector_limit = number of total test vectors in one function will exceed limit ({$max_num_test_vectors}) if this decision is instrumented, so MC/DC analysis ignores it
|
||||||
|
|
||||||
mir_transform_ffi_unwind_call = call to {$foreign ->
|
mir_transform_ffi_unwind_call = call to {$foreign ->
|
||||||
[true] foreign function
|
[true] foreign function
|
||||||
*[false] function pointer
|
*[false] function pointer
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
use std::collections::BTreeSet;
|
use std::collections::BTreeSet;
|
||||||
|
|
||||||
|
use rustc_data_structures::fx::FxIndexMap;
|
||||||
use rustc_data_structures::graph::DirectedGraph;
|
use rustc_data_structures::graph::DirectedGraph;
|
||||||
use rustc_index::IndexVec;
|
use rustc_index::IndexVec;
|
||||||
use rustc_index::bit_set::BitSet;
|
use rustc_index::bit_set::BitSet;
|
||||||
use rustc_middle::mir::coverage::{
|
use rustc_middle::mir::coverage::{
|
||||||
BlockMarkerId, BranchSpan, ConditionInfo, CoverageInfoHi, CoverageKind,
|
BlockMarkerId, BranchSpan, ConditionId, ConditionInfo, CoverageInfoHi, CoverageKind,
|
||||||
};
|
};
|
||||||
use rustc_middle::mir::{self, BasicBlock, StatementKind};
|
use rustc_middle::mir::{self, BasicBlock, StatementKind};
|
||||||
use rustc_middle::ty::TyCtxt;
|
use rustc_middle::ty::TyCtxt;
|
||||||
@ -14,6 +15,7 @@ use crate::coverage::ExtractedHirInfo;
|
|||||||
use crate::coverage::graph::{BasicCoverageBlock, CoverageGraph, START_BCB};
|
use crate::coverage::graph::{BasicCoverageBlock, CoverageGraph, START_BCB};
|
||||||
use crate::coverage::spans::extract_refined_covspans;
|
use crate::coverage::spans::extract_refined_covspans;
|
||||||
use crate::coverage::unexpand::unexpand_into_body_span;
|
use crate::coverage::unexpand::unexpand_into_body_span;
|
||||||
|
use crate::errors::MCDCExceedsTestVectorLimit;
|
||||||
|
|
||||||
/// Associates an ordinary executable code span with its corresponding BCB.
|
/// Associates an ordinary executable code span with its corresponding BCB.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -38,10 +40,11 @@ pub(super) struct MCDCBranch {
|
|||||||
pub(super) span: Span,
|
pub(super) span: Span,
|
||||||
pub(super) true_bcb: BasicCoverageBlock,
|
pub(super) true_bcb: BasicCoverageBlock,
|
||||||
pub(super) false_bcb: BasicCoverageBlock,
|
pub(super) false_bcb: BasicCoverageBlock,
|
||||||
/// If `None`, this actually represents a normal branch mapping inserted
|
pub(super) condition_info: ConditionInfo,
|
||||||
/// for code that was too complex for MC/DC.
|
// Offset added to test vector idx if this branch is evaluated to true.
|
||||||
pub(super) condition_info: Option<ConditionInfo>,
|
pub(super) true_index: usize,
|
||||||
pub(super) decision_depth: u16,
|
// Offset added to test vector idx if this branch is evaluated to false.
|
||||||
|
pub(super) false_index: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Associates an MC/DC decision with its join BCBs.
|
/// Associates an MC/DC decision with its join BCBs.
|
||||||
@ -49,11 +52,15 @@ pub(super) struct MCDCBranch {
|
|||||||
pub(super) struct MCDCDecision {
|
pub(super) struct MCDCDecision {
|
||||||
pub(super) span: Span,
|
pub(super) span: Span,
|
||||||
pub(super) end_bcbs: BTreeSet<BasicCoverageBlock>,
|
pub(super) end_bcbs: BTreeSet<BasicCoverageBlock>,
|
||||||
pub(super) bitmap_idx: u32,
|
pub(super) bitmap_idx: usize,
|
||||||
pub(super) num_conditions: u16,
|
pub(super) num_test_vectors: usize,
|
||||||
pub(super) decision_depth: u16,
|
pub(super) decision_depth: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LLVM uses `i32` to index the bitmap. Thus `i32::MAX` is the hard limit for number of all test vectors
|
||||||
|
// in a function.
|
||||||
|
const MCDC_MAX_BITMAP_SIZE: usize = i32::MAX as usize;
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub(super) struct ExtractedMappings {
|
pub(super) struct ExtractedMappings {
|
||||||
/// Store our own copy of [`CoverageGraph::num_nodes`], so that we don't
|
/// Store our own copy of [`CoverageGraph::num_nodes`], so that we don't
|
||||||
@ -62,9 +69,9 @@ pub(super) struct ExtractedMappings {
|
|||||||
pub(super) num_bcbs: usize,
|
pub(super) num_bcbs: usize,
|
||||||
pub(super) code_mappings: Vec<CodeMapping>,
|
pub(super) code_mappings: Vec<CodeMapping>,
|
||||||
pub(super) branch_pairs: Vec<BranchPair>,
|
pub(super) branch_pairs: Vec<BranchPair>,
|
||||||
pub(super) mcdc_bitmap_bytes: u32,
|
pub(super) mcdc_bitmap_bits: usize,
|
||||||
pub(super) mcdc_branches: Vec<MCDCBranch>,
|
pub(super) mcdc_degraded_branches: Vec<MCDCBranch>,
|
||||||
pub(super) mcdc_decisions: Vec<MCDCDecision>,
|
pub(super) mcdc_mappings: Vec<(MCDCDecision, Vec<MCDCBranch>)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Extracts coverage-relevant spans from MIR, and associates them with
|
/// Extracts coverage-relevant spans from MIR, and associates them with
|
||||||
@ -77,9 +84,9 @@ pub(super) fn extract_all_mapping_info_from_mir<'tcx>(
|
|||||||
) -> ExtractedMappings {
|
) -> ExtractedMappings {
|
||||||
let mut code_mappings = vec![];
|
let mut code_mappings = vec![];
|
||||||
let mut branch_pairs = vec![];
|
let mut branch_pairs = vec![];
|
||||||
let mut mcdc_bitmap_bytes = 0;
|
let mut mcdc_bitmap_bits = 0;
|
||||||
let mut mcdc_branches = vec![];
|
let mut mcdc_degraded_branches = vec![];
|
||||||
let mut mcdc_decisions = vec![];
|
let mut mcdc_mappings = vec![];
|
||||||
|
|
||||||
if hir_info.is_async_fn || tcx.sess.coverage_no_mir_spans() {
|
if hir_info.is_async_fn || tcx.sess.coverage_no_mir_spans() {
|
||||||
// An async function desugars into a function that returns a future,
|
// An async function desugars into a function that returns a future,
|
||||||
@ -102,20 +109,21 @@ pub(super) fn extract_all_mapping_info_from_mir<'tcx>(
|
|||||||
|
|
||||||
extract_mcdc_mappings(
|
extract_mcdc_mappings(
|
||||||
mir_body,
|
mir_body,
|
||||||
|
tcx,
|
||||||
hir_info.body_span,
|
hir_info.body_span,
|
||||||
basic_coverage_blocks,
|
basic_coverage_blocks,
|
||||||
&mut mcdc_bitmap_bytes,
|
&mut mcdc_bitmap_bits,
|
||||||
&mut mcdc_branches,
|
&mut mcdc_degraded_branches,
|
||||||
&mut mcdc_decisions,
|
&mut mcdc_mappings,
|
||||||
);
|
);
|
||||||
|
|
||||||
ExtractedMappings {
|
ExtractedMappings {
|
||||||
num_bcbs: basic_coverage_blocks.num_nodes(),
|
num_bcbs: basic_coverage_blocks.num_nodes(),
|
||||||
code_mappings,
|
code_mappings,
|
||||||
branch_pairs,
|
branch_pairs,
|
||||||
mcdc_bitmap_bytes,
|
mcdc_bitmap_bits,
|
||||||
mcdc_branches,
|
mcdc_degraded_branches,
|
||||||
mcdc_decisions,
|
mcdc_mappings,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,9 +134,9 @@ impl ExtractedMappings {
|
|||||||
num_bcbs,
|
num_bcbs,
|
||||||
code_mappings,
|
code_mappings,
|
||||||
branch_pairs,
|
branch_pairs,
|
||||||
mcdc_bitmap_bytes: _,
|
mcdc_bitmap_bits: _,
|
||||||
mcdc_branches,
|
mcdc_degraded_branches,
|
||||||
mcdc_decisions,
|
mcdc_mappings,
|
||||||
} = self;
|
} = self;
|
||||||
|
|
||||||
// Identify which BCBs have one or more mappings.
|
// Identify which BCBs have one or more mappings.
|
||||||
@ -144,7 +152,10 @@ impl ExtractedMappings {
|
|||||||
insert(true_bcb);
|
insert(true_bcb);
|
||||||
insert(false_bcb);
|
insert(false_bcb);
|
||||||
}
|
}
|
||||||
for &MCDCBranch { true_bcb, false_bcb, .. } in mcdc_branches {
|
for &MCDCBranch { true_bcb, false_bcb, .. } in mcdc_degraded_branches
|
||||||
|
.iter()
|
||||||
|
.chain(mcdc_mappings.iter().map(|(_, branches)| branches.into_iter()).flatten())
|
||||||
|
{
|
||||||
insert(true_bcb);
|
insert(true_bcb);
|
||||||
insert(false_bcb);
|
insert(false_bcb);
|
||||||
}
|
}
|
||||||
@ -152,8 +163,8 @@ impl ExtractedMappings {
|
|||||||
// MC/DC decisions refer to BCBs, but don't require those BCBs to have counters.
|
// MC/DC decisions refer to BCBs, but don't require those BCBs to have counters.
|
||||||
if bcbs_with_counter_mappings.is_empty() {
|
if bcbs_with_counter_mappings.is_empty() {
|
||||||
debug_assert!(
|
debug_assert!(
|
||||||
mcdc_decisions.is_empty(),
|
mcdc_mappings.is_empty(),
|
||||||
"A function with no counter mappings shouldn't have any decisions: {mcdc_decisions:?}",
|
"A function with no counter mappings shouldn't have any decisions: {mcdc_mappings:?}",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -230,11 +241,12 @@ pub(super) fn extract_branch_pairs(
|
|||||||
|
|
||||||
pub(super) fn extract_mcdc_mappings(
|
pub(super) fn extract_mcdc_mappings(
|
||||||
mir_body: &mir::Body<'_>,
|
mir_body: &mir::Body<'_>,
|
||||||
|
tcx: TyCtxt<'_>,
|
||||||
body_span: Span,
|
body_span: Span,
|
||||||
basic_coverage_blocks: &CoverageGraph,
|
basic_coverage_blocks: &CoverageGraph,
|
||||||
mcdc_bitmap_bytes: &mut u32,
|
mcdc_bitmap_bits: &mut usize,
|
||||||
mcdc_branches: &mut impl Extend<MCDCBranch>,
|
mcdc_degraded_branches: &mut impl Extend<MCDCBranch>,
|
||||||
mcdc_decisions: &mut impl Extend<MCDCDecision>,
|
mcdc_mappings: &mut impl Extend<(MCDCDecision, Vec<MCDCBranch>)>,
|
||||||
) {
|
) {
|
||||||
let Some(coverage_info_hi) = mir_body.coverage_info_hi.as_deref() else { return };
|
let Some(coverage_info_hi) = mir_body.coverage_info_hi.as_deref() else { return };
|
||||||
|
|
||||||
@ -257,43 +269,146 @@ pub(super) fn extract_mcdc_mappings(
|
|||||||
Some((span, true_bcb, false_bcb))
|
Some((span, true_bcb, false_bcb))
|
||||||
};
|
};
|
||||||
|
|
||||||
mcdc_branches.extend(coverage_info_hi.mcdc_branch_spans.iter().filter_map(
|
let to_mcdc_branch = |&mir::coverage::MCDCBranchSpan {
|
||||||
|&mir::coverage::MCDCBranchSpan {
|
span: raw_span,
|
||||||
span: raw_span,
|
condition_info,
|
||||||
condition_info,
|
true_marker,
|
||||||
true_marker,
|
false_marker,
|
||||||
false_marker,
|
}| {
|
||||||
decision_depth,
|
let (span, true_bcb, false_bcb) = check_branch_bcb(raw_span, true_marker, false_marker)?;
|
||||||
}| {
|
Some(MCDCBranch {
|
||||||
let (span, true_bcb, false_bcb) =
|
span,
|
||||||
check_branch_bcb(raw_span, true_marker, false_marker)?;
|
true_bcb,
|
||||||
Some(MCDCBranch { span, true_bcb, false_bcb, condition_info, decision_depth })
|
false_bcb,
|
||||||
},
|
condition_info,
|
||||||
));
|
true_index: usize::MAX,
|
||||||
|
false_index: usize::MAX,
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
mcdc_decisions.extend(coverage_info_hi.mcdc_decision_spans.iter().filter_map(
|
let mut get_bitmap_idx = |num_test_vectors: usize| -> Option<usize> {
|
||||||
|decision: &mir::coverage::MCDCDecisionSpan| {
|
let bitmap_idx = *mcdc_bitmap_bits;
|
||||||
let span = unexpand_into_body_span(decision.span, body_span)?;
|
let next_bitmap_bits = bitmap_idx.saturating_add(num_test_vectors);
|
||||||
|
(next_bitmap_bits <= MCDC_MAX_BITMAP_SIZE).then(|| {
|
||||||
|
*mcdc_bitmap_bits = next_bitmap_bits;
|
||||||
|
bitmap_idx
|
||||||
|
})
|
||||||
|
};
|
||||||
|
mcdc_degraded_branches
|
||||||
|
.extend(coverage_info_hi.mcdc_degraded_branch_spans.iter().filter_map(to_mcdc_branch));
|
||||||
|
|
||||||
let end_bcbs = decision
|
mcdc_mappings.extend(coverage_info_hi.mcdc_spans.iter().filter_map(|(decision, branches)| {
|
||||||
.end_markers
|
if branches.len() == 0 {
|
||||||
.iter()
|
return None;
|
||||||
.map(|&marker| bcb_from_marker(marker))
|
}
|
||||||
.collect::<Option<_>>()?;
|
let decision_span = unexpand_into_body_span(decision.span, body_span)?;
|
||||||
|
|
||||||
// Each decision containing N conditions needs 2^N bits of space in
|
let end_bcbs = decision
|
||||||
// the bitmap, rounded up to a whole number of bytes.
|
.end_markers
|
||||||
// The decision's "bitmap index" points to its first byte in the bitmap.
|
.iter()
|
||||||
let bitmap_idx = *mcdc_bitmap_bytes;
|
.map(|&marker| bcb_from_marker(marker))
|
||||||
*mcdc_bitmap_bytes += (1_u32 << decision.num_conditions).div_ceil(8);
|
.collect::<Option<_>>()?;
|
||||||
|
let mut branch_mappings: Vec<_> = branches.into_iter().filter_map(to_mcdc_branch).collect();
|
||||||
Some(MCDCDecision {
|
if branch_mappings.len() != branches.len() {
|
||||||
|
mcdc_degraded_branches.extend(branch_mappings);
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let num_test_vectors = calc_test_vectors_index(&mut branch_mappings);
|
||||||
|
let Some(bitmap_idx) = get_bitmap_idx(num_test_vectors) else {
|
||||||
|
tcx.dcx().emit_warn(MCDCExceedsTestVectorLimit {
|
||||||
|
span: decision_span,
|
||||||
|
max_num_test_vectors: MCDC_MAX_BITMAP_SIZE,
|
||||||
|
});
|
||||||
|
mcdc_degraded_branches.extend(branch_mappings);
|
||||||
|
return None;
|
||||||
|
};
|
||||||
|
// LLVM requires span of the decision contains all spans of its conditions.
|
||||||
|
// Usually the decision span meets the requirement well but in cases like macros it may not.
|
||||||
|
let span = branch_mappings
|
||||||
|
.iter()
|
||||||
|
.map(|branch| branch.span)
|
||||||
|
.reduce(|lhs, rhs| lhs.to(rhs))
|
||||||
|
.map(
|
||||||
|
|joint_span| {
|
||||||
|
if decision_span.contains(joint_span) { decision_span } else { joint_span }
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.expect("branch mappings are ensured to be non-empty as checked above");
|
||||||
|
Some((
|
||||||
|
MCDCDecision {
|
||||||
span,
|
span,
|
||||||
end_bcbs,
|
end_bcbs,
|
||||||
bitmap_idx,
|
bitmap_idx,
|
||||||
num_conditions: decision.num_conditions as u16,
|
num_test_vectors,
|
||||||
decision_depth: decision.decision_depth,
|
decision_depth: decision.decision_depth,
|
||||||
})
|
},
|
||||||
},
|
branch_mappings,
|
||||||
));
|
))
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
// LLVM checks the executed test vector by accumulating indices of tested branches.
|
||||||
|
// We calculate number of all possible test vectors of the decision and assign indices
|
||||||
|
// to branches here.
|
||||||
|
// See [the rfc](https://discourse.llvm.org/t/rfc-coverage-new-algorithm-and-file-format-for-mc-dc/76798/)
|
||||||
|
// for more details about the algorithm.
|
||||||
|
// This function is mostly like [`TVIdxBuilder::TvIdxBuilder`](https://github.com/llvm/llvm-project/blob/d594d9f7f4dc6eb748b3261917db689fdc348b96/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp#L226)
|
||||||
|
fn calc_test_vectors_index(conditions: &mut Vec<MCDCBranch>) -> usize {
|
||||||
|
let mut indegree_stats = IndexVec::<ConditionId, usize>::from_elem_n(0, conditions.len());
|
||||||
|
// `num_paths` is `width` described at the llvm rfc, which indicates how many paths reaching the condition node.
|
||||||
|
let mut num_paths_stats = IndexVec::<ConditionId, usize>::from_elem_n(0, conditions.len());
|
||||||
|
let mut next_conditions = conditions
|
||||||
|
.iter_mut()
|
||||||
|
.map(|branch| {
|
||||||
|
let ConditionInfo { condition_id, true_next_id, false_next_id } = branch.condition_info;
|
||||||
|
[true_next_id, false_next_id]
|
||||||
|
.into_iter()
|
||||||
|
.filter_map(std::convert::identity)
|
||||||
|
.for_each(|next_id| indegree_stats[next_id] += 1);
|
||||||
|
(condition_id, branch)
|
||||||
|
})
|
||||||
|
.collect::<FxIndexMap<_, _>>();
|
||||||
|
|
||||||
|
let mut queue = std::collections::VecDeque::from_iter(
|
||||||
|
next_conditions.swap_remove(&ConditionId::START).into_iter(),
|
||||||
|
);
|
||||||
|
num_paths_stats[ConditionId::START] = 1;
|
||||||
|
let mut decision_end_nodes = Vec::new();
|
||||||
|
while let Some(branch) = queue.pop_front() {
|
||||||
|
let ConditionInfo { condition_id, true_next_id, false_next_id } = branch.condition_info;
|
||||||
|
let (false_index, true_index) = (&mut branch.false_index, &mut branch.true_index);
|
||||||
|
let this_paths_count = num_paths_stats[condition_id];
|
||||||
|
// Note. First check the false next to ensure conditions are touched in same order with llvm-cov.
|
||||||
|
for (next, index) in [(false_next_id, false_index), (true_next_id, true_index)] {
|
||||||
|
if let Some(next_id) = next {
|
||||||
|
let next_paths_count = &mut num_paths_stats[next_id];
|
||||||
|
*index = *next_paths_count;
|
||||||
|
*next_paths_count = next_paths_count.saturating_add(this_paths_count);
|
||||||
|
let next_indegree = &mut indegree_stats[next_id];
|
||||||
|
*next_indegree -= 1;
|
||||||
|
if *next_indegree == 0 {
|
||||||
|
queue.push_back(next_conditions.swap_remove(&next_id).expect(
|
||||||
|
"conditions with non-zero indegree before must be in next_conditions",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
decision_end_nodes.push((this_paths_count, condition_id, index));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert!(next_conditions.is_empty(), "the decision tree has untouched nodes");
|
||||||
|
let mut cur_idx = 0;
|
||||||
|
// LLVM hopes the end nodes are sorted in descending order by `num_paths` so that it can
|
||||||
|
// optimize bitmap size for decisions in tree form such as `a && b && c && d && ...`.
|
||||||
|
decision_end_nodes.sort_by_key(|(num_paths, _, _)| usize::MAX - *num_paths);
|
||||||
|
for (num_paths, condition_id, index) in decision_end_nodes {
|
||||||
|
assert_eq!(
|
||||||
|
num_paths, num_paths_stats[condition_id],
|
||||||
|
"end nodes should not be updated since they were visited"
|
||||||
|
);
|
||||||
|
assert_eq!(*index, usize::MAX, "end nodes should not be assigned index before");
|
||||||
|
*index = cur_idx;
|
||||||
|
cur_idx += num_paths;
|
||||||
|
}
|
||||||
|
cur_idx
|
||||||
}
|
}
|
||||||
|
@ -114,16 +114,16 @@ fn instrument_function_for_coverage<'tcx>(tcx: TyCtxt<'tcx>, mir_body: &mut mir:
|
|||||||
inject_mcdc_statements(mir_body, &basic_coverage_blocks, &extracted_mappings);
|
inject_mcdc_statements(mir_body, &basic_coverage_blocks, &extracted_mappings);
|
||||||
|
|
||||||
let mcdc_num_condition_bitmaps = extracted_mappings
|
let mcdc_num_condition_bitmaps = extracted_mappings
|
||||||
.mcdc_decisions
|
.mcdc_mappings
|
||||||
.iter()
|
.iter()
|
||||||
.map(|&mappings::MCDCDecision { decision_depth, .. }| decision_depth)
|
.map(|&(mappings::MCDCDecision { decision_depth, .. }, _)| decision_depth)
|
||||||
.max()
|
.max()
|
||||||
.map_or(0, |max| usize::from(max) + 1);
|
.map_or(0, |max| usize::from(max) + 1);
|
||||||
|
|
||||||
mir_body.function_coverage_info = Some(Box::new(FunctionCoverageInfo {
|
mir_body.function_coverage_info = Some(Box::new(FunctionCoverageInfo {
|
||||||
function_source_hash: hir_info.function_source_hash,
|
function_source_hash: hir_info.function_source_hash,
|
||||||
num_counters: coverage_counters.num_counters(),
|
num_counters: coverage_counters.num_counters(),
|
||||||
mcdc_bitmap_bytes: extracted_mappings.mcdc_bitmap_bytes,
|
mcdc_bitmap_bits: extracted_mappings.mcdc_bitmap_bits,
|
||||||
expressions: coverage_counters.into_expressions(),
|
expressions: coverage_counters.into_expressions(),
|
||||||
mappings,
|
mappings,
|
||||||
mcdc_num_condition_bitmaps,
|
mcdc_num_condition_bitmaps,
|
||||||
@ -161,9 +161,9 @@ fn create_mappings<'tcx>(
|
|||||||
num_bcbs: _,
|
num_bcbs: _,
|
||||||
code_mappings,
|
code_mappings,
|
||||||
branch_pairs,
|
branch_pairs,
|
||||||
mcdc_bitmap_bytes: _,
|
mcdc_bitmap_bits: _,
|
||||||
mcdc_branches,
|
mcdc_degraded_branches,
|
||||||
mcdc_decisions,
|
mcdc_mappings,
|
||||||
} = extracted_mappings;
|
} = extracted_mappings;
|
||||||
let mut mappings = Vec::new();
|
let mut mappings = Vec::new();
|
||||||
|
|
||||||
@ -186,26 +186,79 @@ fn create_mappings<'tcx>(
|
|||||||
},
|
},
|
||||||
));
|
));
|
||||||
|
|
||||||
mappings.extend(mcdc_branches.iter().filter_map(
|
let term_for_bcb =
|
||||||
|&mappings::MCDCBranch { span, true_bcb, false_bcb, condition_info, decision_depth: _ }| {
|
|bcb| coverage_counters.term_for_bcb(bcb).expect("all BCBs with spans were given counters");
|
||||||
|
|
||||||
|
// MCDC branch mappings are appended with their decisions in case decisions were ignored.
|
||||||
|
mappings.extend(mcdc_degraded_branches.iter().filter_map(
|
||||||
|
|&mappings::MCDCBranch {
|
||||||
|
span,
|
||||||
|
true_bcb,
|
||||||
|
false_bcb,
|
||||||
|
condition_info: _,
|
||||||
|
true_index: _,
|
||||||
|
false_index: _,
|
||||||
|
}| {
|
||||||
let source_region = region_for_span(span)?;
|
let source_region = region_for_span(span)?;
|
||||||
let true_term = term_for_bcb(true_bcb);
|
let true_term = term_for_bcb(true_bcb);
|
||||||
let false_term = term_for_bcb(false_bcb);
|
let false_term = term_for_bcb(false_bcb);
|
||||||
let kind = match condition_info {
|
Some(Mapping { kind: MappingKind::Branch { true_term, false_term }, source_region })
|
||||||
Some(mcdc_params) => MappingKind::MCDCBranch { true_term, false_term, mcdc_params },
|
|
||||||
None => MappingKind::Branch { true_term, false_term },
|
|
||||||
};
|
|
||||||
Some(Mapping { kind, source_region })
|
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
|
|
||||||
mappings.extend(mcdc_decisions.iter().filter_map(
|
for (decision, branches) in mcdc_mappings {
|
||||||
|&mappings::MCDCDecision { span, bitmap_idx, num_conditions, .. }| {
|
let num_conditions = branches.len() as u16;
|
||||||
let source_region = region_for_span(span)?;
|
let conditions = branches
|
||||||
let kind = MappingKind::MCDCDecision(DecisionInfo { bitmap_idx, num_conditions });
|
.into_iter()
|
||||||
Some(Mapping { kind, source_region })
|
.filter_map(
|
||||||
},
|
|&mappings::MCDCBranch {
|
||||||
));
|
span,
|
||||||
|
true_bcb,
|
||||||
|
false_bcb,
|
||||||
|
condition_info,
|
||||||
|
true_index: _,
|
||||||
|
false_index: _,
|
||||||
|
}| {
|
||||||
|
let source_region = region_for_span(span)?;
|
||||||
|
let true_term = term_for_bcb(true_bcb);
|
||||||
|
let false_term = term_for_bcb(false_bcb);
|
||||||
|
Some(Mapping {
|
||||||
|
kind: MappingKind::MCDCBranch {
|
||||||
|
true_term,
|
||||||
|
false_term,
|
||||||
|
mcdc_params: condition_info,
|
||||||
|
},
|
||||||
|
source_region,
|
||||||
|
})
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
if conditions.len() == num_conditions as usize
|
||||||
|
&& let Some(source_region) = region_for_span(decision.span)
|
||||||
|
{
|
||||||
|
// LLVM requires end index for counter mapping regions.
|
||||||
|
let kind = MappingKind::MCDCDecision(DecisionInfo {
|
||||||
|
bitmap_idx: (decision.bitmap_idx + decision.num_test_vectors) as u32,
|
||||||
|
num_conditions,
|
||||||
|
});
|
||||||
|
mappings.extend(
|
||||||
|
std::iter::once(Mapping { kind, source_region }).chain(conditions.into_iter()),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
mappings.extend(conditions.into_iter().map(|mapping| {
|
||||||
|
let MappingKind::MCDCBranch { true_term, false_term, mcdc_params: _ } =
|
||||||
|
mapping.kind
|
||||||
|
else {
|
||||||
|
unreachable!("all mappings here are MCDCBranch as shown above");
|
||||||
|
};
|
||||||
|
Mapping {
|
||||||
|
kind: MappingKind::Branch { true_term, false_term },
|
||||||
|
source_region: mapping.source_region,
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mappings
|
mappings
|
||||||
}
|
}
|
||||||
@ -274,44 +327,41 @@ fn inject_mcdc_statements<'tcx>(
|
|||||||
basic_coverage_blocks: &CoverageGraph,
|
basic_coverage_blocks: &CoverageGraph,
|
||||||
extracted_mappings: &ExtractedMappings,
|
extracted_mappings: &ExtractedMappings,
|
||||||
) {
|
) {
|
||||||
// Inject test vector update first because `inject_statement` always insert new statement at
|
for (decision, conditions) in &extracted_mappings.mcdc_mappings {
|
||||||
// head.
|
// Inject test vector update first because `inject_statement` always insert new statement at head.
|
||||||
for &mappings::MCDCDecision {
|
for &end in &decision.end_bcbs {
|
||||||
span: _,
|
let end_bb = basic_coverage_blocks[end].leader_bb();
|
||||||
ref end_bcbs,
|
|
||||||
bitmap_idx,
|
|
||||||
num_conditions: _,
|
|
||||||
decision_depth,
|
|
||||||
} in &extracted_mappings.mcdc_decisions
|
|
||||||
{
|
|
||||||
for end in end_bcbs {
|
|
||||||
let end_bb = basic_coverage_blocks[*end].leader_bb();
|
|
||||||
inject_statement(
|
inject_statement(
|
||||||
mir_body,
|
mir_body,
|
||||||
CoverageKind::TestVectorBitmapUpdate { bitmap_idx, decision_depth },
|
CoverageKind::TestVectorBitmapUpdate {
|
||||||
|
bitmap_idx: decision.bitmap_idx as u32,
|
||||||
|
decision_depth: decision.decision_depth,
|
||||||
|
},
|
||||||
end_bb,
|
end_bb,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
for &mappings::MCDCBranch { span: _, true_bcb, false_bcb, condition_info, decision_depth } in
|
for &mappings::MCDCBranch {
|
||||||
&extracted_mappings.mcdc_branches
|
span: _,
|
||||||
{
|
true_bcb,
|
||||||
let Some(condition_info) = condition_info else { continue };
|
false_bcb,
|
||||||
let id = condition_info.condition_id;
|
condition_info: _,
|
||||||
|
true_index,
|
||||||
let true_bb = basic_coverage_blocks[true_bcb].leader_bb();
|
false_index,
|
||||||
inject_statement(
|
} in conditions
|
||||||
mir_body,
|
{
|
||||||
CoverageKind::CondBitmapUpdate { id, value: true, decision_depth },
|
for (index, bcb) in [(false_index, false_bcb), (true_index, true_bcb)] {
|
||||||
true_bb,
|
let bb = basic_coverage_blocks[bcb].leader_bb();
|
||||||
);
|
inject_statement(
|
||||||
let false_bb = basic_coverage_blocks[false_bcb].leader_bb();
|
mir_body,
|
||||||
inject_statement(
|
CoverageKind::CondBitmapUpdate {
|
||||||
mir_body,
|
index: index as u32,
|
||||||
CoverageKind::CondBitmapUpdate { id, value: false, decision_depth },
|
decision_depth: decision.decision_depth,
|
||||||
false_bb,
|
},
|
||||||
);
|
bb,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,6 +89,14 @@ pub(crate) struct FnItemRef {
|
|||||||
pub ident: String,
|
pub ident: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(mir_transform_exceeds_mcdc_test_vector_limit)]
|
||||||
|
pub(crate) struct MCDCExceedsTestVectorLimit {
|
||||||
|
#[primary_span]
|
||||||
|
pub(crate) span: Span,
|
||||||
|
pub(crate) max_num_test_vectors: usize,
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) struct MustNotSupend<'a, 'tcx> {
|
pub(crate) struct MustNotSupend<'a, 'tcx> {
|
||||||
pub tcx: TyCtxt<'tcx>,
|
pub tcx: TyCtxt<'tcx>,
|
||||||
pub yield_sp: Span,
|
pub yield_sp: Span,
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
Function name: condition_limit::bad
|
Function name: condition_limit::accept_7_conditions
|
||||||
Raw bytes (204): 0x[01, 01, 2c, 01, 05, 05, 1d, 05, 1d, 7a, 19, 05, 1d, 7a, 19, 05, 1d, 76, 15, 7a, 19, 05, 1d, 76, 15, 7a, 19, 05, 1d, 72, 11, 76, 15, 7a, 19, 05, 1d, 72, 11, 76, 15, 7a, 19, 05, 1d, 6e, 0d, 72, 11, 76, 15, 7a, 19, 05, 1d, 6e, 0d, 72, 11, 76, 15, 7a, 19, 05, 1d, 9f, 01, 02, a3, 01, 1d, a7, 01, 19, ab, 01, 15, af, 01, 11, 09, 0d, 21, 9b, 01, 9f, 01, 02, a3, 01, 1d, a7, 01, 19, ab, 01, 15, af, 01, 11, 09, 0d, 11, 01, 14, 01, 03, 09, 20, 05, 02, 03, 08, 00, 09, 05, 00, 0d, 00, 0e, 20, 7a, 1d, 00, 0d, 00, 0e, 7a, 00, 12, 00, 13, 20, 76, 19, 00, 12, 00, 13, 76, 00, 17, 00, 18, 20, 72, 15, 00, 17, 00, 18, 72, 00, 1c, 00, 1d, 20, 6e, 11, 00, 1c, 00, 1d, 6e, 00, 21, 00, 22, 20, 6a, 0d, 00, 21, 00, 22, 6a, 00, 26, 00, 27, 20, 21, 09, 00, 26, 00, 27, 21, 00, 28, 02, 06, 9b, 01, 02, 06, 00, 07, 97, 01, 01, 01, 00, 02]
|
Raw bytes (232): 0x[01, 01, 2c, 01, 05, 05, 1d, 05, 1d, 7a, 19, 05, 1d, 7a, 19, 05, 1d, 76, 15, 7a, 19, 05, 1d, 76, 15, 7a, 19, 05, 1d, 72, 11, 76, 15, 7a, 19, 05, 1d, 72, 11, 76, 15, 7a, 19, 05, 1d, 6e, 0d, 72, 11, 76, 15, 7a, 19, 05, 1d, 6e, 0d, 72, 11, 76, 15, 7a, 19, 05, 1d, 9f, 01, 02, a3, 01, 1d, a7, 01, 19, ab, 01, 15, af, 01, 11, 09, 0d, 21, 9b, 01, 9f, 01, 02, a3, 01, 1d, a7, 01, 19, ab, 01, 15, af, 01, 11, 09, 0d, 12, 01, 07, 01, 02, 09, 28, 08, 07, 02, 08, 00, 27, 30, 05, 02, 01, 07, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 7a, 1d, 07, 06, 00, 00, 0d, 00, 0e, 7a, 00, 12, 00, 13, 30, 76, 19, 06, 05, 00, 00, 12, 00, 13, 76, 00, 17, 00, 18, 30, 72, 15, 05, 04, 00, 00, 17, 00, 18, 72, 00, 1c, 00, 1d, 30, 6e, 11, 04, 03, 00, 00, 1c, 00, 1d, 6e, 00, 21, 00, 22, 30, 6a, 0d, 03, 02, 00, 00, 21, 00, 22, 6a, 00, 26, 00, 27, 30, 21, 09, 02, 00, 00, 00, 26, 00, 27, 21, 00, 28, 02, 06, 9b, 01, 02, 06, 00, 07, 97, 01, 01, 01, 00, 02]
|
||||||
Number of files: 1
|
Number of files: 1
|
||||||
- file 0 => global file 1
|
- file 0 => global file 1
|
||||||
Number of expressions: 44
|
Number of expressions: 44
|
||||||
@ -47,38 +47,39 @@ Number of expressions: 44
|
|||||||
- expression 41 operands: lhs = Expression(42, Add), rhs = Counter(5)
|
- expression 41 operands: lhs = Expression(42, Add), rhs = Counter(5)
|
||||||
- expression 42 operands: lhs = Expression(43, Add), rhs = Counter(4)
|
- expression 42 operands: lhs = Expression(43, Add), rhs = Counter(4)
|
||||||
- expression 43 operands: lhs = Counter(2), rhs = Counter(3)
|
- expression 43 operands: lhs = Counter(2), rhs = Counter(3)
|
||||||
Number of file 0 mappings: 17
|
Number of file 0 mappings: 18
|
||||||
- Code(Counter(0)) at (prev + 20, 1) to (start + 3, 9)
|
- Code(Counter(0)) at (prev + 7, 1) to (start + 2, 9)
|
||||||
- Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 3, 8) to (start + 0, 9)
|
- MCDCDecision { bitmap_idx: 8, conditions_num: 7 } at (prev + 2, 8) to (start + 0, 39)
|
||||||
|
- MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 7, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9)
|
||||||
true = c1
|
true = c1
|
||||||
false = (c0 - c1)
|
false = (c0 - c1)
|
||||||
- Code(Counter(1)) at (prev + 0, 13) to (start + 0, 14)
|
- Code(Counter(1)) at (prev + 0, 13) to (start + 0, 14)
|
||||||
- Branch { true: Expression(30, Sub), false: Counter(7) } at (prev + 0, 13) to (start + 0, 14)
|
- MCDCBranch { true: Expression(30, Sub), false: Counter(7), condition_id: 7, true_next_id: 6, false_next_id: 0 } at (prev + 0, 13) to (start + 0, 14)
|
||||||
true = (c1 - c7)
|
true = (c1 - c7)
|
||||||
false = c7
|
false = c7
|
||||||
- Code(Expression(30, Sub)) at (prev + 0, 18) to (start + 0, 19)
|
- Code(Expression(30, Sub)) at (prev + 0, 18) to (start + 0, 19)
|
||||||
= (c1 - c7)
|
= (c1 - c7)
|
||||||
- Branch { true: Expression(29, Sub), false: Counter(6) } at (prev + 0, 18) to (start + 0, 19)
|
- MCDCBranch { true: Expression(29, Sub), false: Counter(6), condition_id: 6, true_next_id: 5, false_next_id: 0 } at (prev + 0, 18) to (start + 0, 19)
|
||||||
true = ((c1 - c7) - c6)
|
true = ((c1 - c7) - c6)
|
||||||
false = c6
|
false = c6
|
||||||
- Code(Expression(29, Sub)) at (prev + 0, 23) to (start + 0, 24)
|
- Code(Expression(29, Sub)) at (prev + 0, 23) to (start + 0, 24)
|
||||||
= ((c1 - c7) - c6)
|
= ((c1 - c7) - c6)
|
||||||
- Branch { true: Expression(28, Sub), false: Counter(5) } at (prev + 0, 23) to (start + 0, 24)
|
- MCDCBranch { true: Expression(28, Sub), false: Counter(5), condition_id: 5, true_next_id: 4, false_next_id: 0 } at (prev + 0, 23) to (start + 0, 24)
|
||||||
true = (((c1 - c7) - c6) - c5)
|
true = (((c1 - c7) - c6) - c5)
|
||||||
false = c5
|
false = c5
|
||||||
- Code(Expression(28, Sub)) at (prev + 0, 28) to (start + 0, 29)
|
- Code(Expression(28, Sub)) at (prev + 0, 28) to (start + 0, 29)
|
||||||
= (((c1 - c7) - c6) - c5)
|
= (((c1 - c7) - c6) - c5)
|
||||||
- Branch { true: Expression(27, Sub), false: Counter(4) } at (prev + 0, 28) to (start + 0, 29)
|
- MCDCBranch { true: Expression(27, Sub), false: Counter(4), condition_id: 4, true_next_id: 3, false_next_id: 0 } at (prev + 0, 28) to (start + 0, 29)
|
||||||
true = ((((c1 - c7) - c6) - c5) - c4)
|
true = ((((c1 - c7) - c6) - c5) - c4)
|
||||||
false = c4
|
false = c4
|
||||||
- Code(Expression(27, Sub)) at (prev + 0, 33) to (start + 0, 34)
|
- Code(Expression(27, Sub)) at (prev + 0, 33) to (start + 0, 34)
|
||||||
= ((((c1 - c7) - c6) - c5) - c4)
|
= ((((c1 - c7) - c6) - c5) - c4)
|
||||||
- Branch { true: Expression(26, Sub), false: Counter(3) } at (prev + 0, 33) to (start + 0, 34)
|
- MCDCBranch { true: Expression(26, Sub), false: Counter(3), condition_id: 3, true_next_id: 2, false_next_id: 0 } at (prev + 0, 33) to (start + 0, 34)
|
||||||
true = (((((c1 - c7) - c6) - c5) - c4) - c3)
|
true = (((((c1 - c7) - c6) - c5) - c4) - c3)
|
||||||
false = c3
|
false = c3
|
||||||
- Code(Expression(26, Sub)) at (prev + 0, 38) to (start + 0, 39)
|
- Code(Expression(26, Sub)) at (prev + 0, 38) to (start + 0, 39)
|
||||||
= (((((c1 - c7) - c6) - c5) - c4) - c3)
|
= (((((c1 - c7) - c6) - c5) - c4) - c3)
|
||||||
- Branch { true: Counter(8), false: Counter(2) } at (prev + 0, 38) to (start + 0, 39)
|
- MCDCBranch { true: Counter(8), false: Counter(2), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 38) to (start + 0, 39)
|
||||||
true = c8
|
true = c8
|
||||||
false = c2
|
false = c2
|
||||||
- Code(Counter(8)) at (prev + 0, 40) to (start + 2, 6)
|
- Code(Counter(8)) at (prev + 0, 40) to (start + 2, 6)
|
||||||
@ -87,76 +88,3 @@ Number of file 0 mappings: 17
|
|||||||
- Code(Expression(37, Add)) at (prev + 1, 1) to (start + 0, 2)
|
- Code(Expression(37, Add)) at (prev + 1, 1) to (start + 0, 2)
|
||||||
= (c8 + ((((((c2 + c3) + c4) + c5) + c6) + c7) + (c0 - c1)))
|
= (c8 + ((((((c2 + c3) + c4) + c5) + c6) + c7) + (c0 - c1)))
|
||||||
|
|
||||||
Function name: condition_limit::good
|
|
||||||
Raw bytes (180): 0x[01, 01, 20, 01, 05, 05, 19, 05, 19, 52, 15, 05, 19, 52, 15, 05, 19, 4e, 11, 52, 15, 05, 19, 4e, 11, 52, 15, 05, 19, 4a, 0d, 4e, 11, 52, 15, 05, 19, 4a, 0d, 4e, 11, 52, 15, 05, 19, 73, 02, 77, 19, 7b, 15, 7f, 11, 09, 0d, 1d, 6f, 73, 02, 77, 19, 7b, 15, 7f, 11, 09, 0d, 10, 01, 0c, 01, 03, 09, 28, 00, 06, 03, 08, 00, 22, 30, 05, 02, 01, 06, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 52, 19, 06, 05, 00, 00, 0d, 00, 0e, 52, 00, 12, 00, 13, 30, 4e, 15, 05, 04, 00, 00, 12, 00, 13, 4e, 00, 17, 00, 18, 30, 4a, 11, 04, 03, 00, 00, 17, 00, 18, 4a, 00, 1c, 00, 1d, 30, 46, 0d, 03, 02, 00, 00, 1c, 00, 1d, 46, 00, 21, 00, 22, 30, 1d, 09, 02, 00, 00, 00, 21, 00, 22, 1d, 00, 23, 02, 06, 6f, 02, 06, 00, 07, 6b, 01, 01, 00, 02]
|
|
||||||
Number of files: 1
|
|
||||||
- file 0 => global file 1
|
|
||||||
Number of expressions: 32
|
|
||||||
- expression 0 operands: lhs = Counter(0), rhs = Counter(1)
|
|
||||||
- expression 1 operands: lhs = Counter(1), rhs = Counter(6)
|
|
||||||
- expression 2 operands: lhs = Counter(1), rhs = Counter(6)
|
|
||||||
- expression 3 operands: lhs = Expression(20, Sub), rhs = Counter(5)
|
|
||||||
- expression 4 operands: lhs = Counter(1), rhs = Counter(6)
|
|
||||||
- expression 5 operands: lhs = Expression(20, Sub), rhs = Counter(5)
|
|
||||||
- expression 6 operands: lhs = Counter(1), rhs = Counter(6)
|
|
||||||
- expression 7 operands: lhs = Expression(19, Sub), rhs = Counter(4)
|
|
||||||
- expression 8 operands: lhs = Expression(20, Sub), rhs = Counter(5)
|
|
||||||
- expression 9 operands: lhs = Counter(1), rhs = Counter(6)
|
|
||||||
- expression 10 operands: lhs = Expression(19, Sub), rhs = Counter(4)
|
|
||||||
- expression 11 operands: lhs = Expression(20, Sub), rhs = Counter(5)
|
|
||||||
- expression 12 operands: lhs = Counter(1), rhs = Counter(6)
|
|
||||||
- expression 13 operands: lhs = Expression(18, Sub), rhs = Counter(3)
|
|
||||||
- expression 14 operands: lhs = Expression(19, Sub), rhs = Counter(4)
|
|
||||||
- expression 15 operands: lhs = Expression(20, Sub), rhs = Counter(5)
|
|
||||||
- expression 16 operands: lhs = Counter(1), rhs = Counter(6)
|
|
||||||
- expression 17 operands: lhs = Expression(18, Sub), rhs = Counter(3)
|
|
||||||
- expression 18 operands: lhs = Expression(19, Sub), rhs = Counter(4)
|
|
||||||
- expression 19 operands: lhs = Expression(20, Sub), rhs = Counter(5)
|
|
||||||
- expression 20 operands: lhs = Counter(1), rhs = Counter(6)
|
|
||||||
- expression 21 operands: lhs = Expression(28, Add), rhs = Expression(0, Sub)
|
|
||||||
- expression 22 operands: lhs = Expression(29, Add), rhs = Counter(6)
|
|
||||||
- expression 23 operands: lhs = Expression(30, Add), rhs = Counter(5)
|
|
||||||
- expression 24 operands: lhs = Expression(31, Add), rhs = Counter(4)
|
|
||||||
- expression 25 operands: lhs = Counter(2), rhs = Counter(3)
|
|
||||||
- expression 26 operands: lhs = Counter(7), rhs = Expression(27, Add)
|
|
||||||
- expression 27 operands: lhs = Expression(28, Add), rhs = Expression(0, Sub)
|
|
||||||
- expression 28 operands: lhs = Expression(29, Add), rhs = Counter(6)
|
|
||||||
- expression 29 operands: lhs = Expression(30, Add), rhs = Counter(5)
|
|
||||||
- expression 30 operands: lhs = Expression(31, Add), rhs = Counter(4)
|
|
||||||
- expression 31 operands: lhs = Counter(2), rhs = Counter(3)
|
|
||||||
Number of file 0 mappings: 16
|
|
||||||
- Code(Counter(0)) at (prev + 12, 1) to (start + 3, 9)
|
|
||||||
- MCDCDecision { bitmap_idx: 0, conditions_num: 6 } at (prev + 3, 8) to (start + 0, 34)
|
|
||||||
- MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 6, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9)
|
|
||||||
true = c1
|
|
||||||
false = (c0 - c1)
|
|
||||||
- Code(Counter(1)) at (prev + 0, 13) to (start + 0, 14)
|
|
||||||
- MCDCBranch { true: Expression(20, Sub), false: Counter(6), condition_id: 6, true_next_id: 5, false_next_id: 0 } at (prev + 0, 13) to (start + 0, 14)
|
|
||||||
true = (c1 - c6)
|
|
||||||
false = c6
|
|
||||||
- Code(Expression(20, Sub)) at (prev + 0, 18) to (start + 0, 19)
|
|
||||||
= (c1 - c6)
|
|
||||||
- MCDCBranch { true: Expression(19, Sub), false: Counter(5), condition_id: 5, true_next_id: 4, false_next_id: 0 } at (prev + 0, 18) to (start + 0, 19)
|
|
||||||
true = ((c1 - c6) - c5)
|
|
||||||
false = c5
|
|
||||||
- Code(Expression(19, Sub)) at (prev + 0, 23) to (start + 0, 24)
|
|
||||||
= ((c1 - c6) - c5)
|
|
||||||
- MCDCBranch { true: Expression(18, Sub), false: Counter(4), condition_id: 4, true_next_id: 3, false_next_id: 0 } at (prev + 0, 23) to (start + 0, 24)
|
|
||||||
true = (((c1 - c6) - c5) - c4)
|
|
||||||
false = c4
|
|
||||||
- Code(Expression(18, Sub)) at (prev + 0, 28) to (start + 0, 29)
|
|
||||||
= (((c1 - c6) - c5) - c4)
|
|
||||||
- MCDCBranch { true: Expression(17, Sub), false: Counter(3), condition_id: 3, true_next_id: 2, false_next_id: 0 } at (prev + 0, 28) to (start + 0, 29)
|
|
||||||
true = ((((c1 - c6) - c5) - c4) - c3)
|
|
||||||
false = c3
|
|
||||||
- Code(Expression(17, Sub)) at (prev + 0, 33) to (start + 0, 34)
|
|
||||||
= ((((c1 - c6) - c5) - c4) - c3)
|
|
||||||
- MCDCBranch { true: Counter(7), false: Counter(2), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 33) to (start + 0, 34)
|
|
||||||
true = c7
|
|
||||||
false = c2
|
|
||||||
- Code(Counter(7)) at (prev + 0, 35) to (start + 2, 6)
|
|
||||||
- Code(Expression(27, Add)) at (prev + 2, 6) to (start + 0, 7)
|
|
||||||
= (((((c2 + c3) + c4) + c5) + c6) + (c0 - c1))
|
|
||||||
- Code(Expression(26, Add)) at (prev + 1, 1) to (start + 0, 2)
|
|
||||||
= (c7 + (((((c2 + c3) + c4) + c5) + c6) + (c0 - c1)))
|
|
||||||
|
|
||||||
|
@ -1,76 +1,56 @@
|
|||||||
LL| |#![feature(coverage_attribute)]
|
LL| |#![feature(coverage_attribute)]
|
||||||
LL| |//@ edition: 2021
|
LL| |//@ edition: 2021
|
||||||
LL| |//@ ignore-llvm-version: 19 - 99
|
LL| |//@ min-llvm-version: 19
|
||||||
LL| |//@ compile-flags: -Zcoverage-options=mcdc
|
LL| |//@ compile-flags: -Zcoverage-options=mcdc
|
||||||
LL| |//@ llvm-cov-flags: --show-branches=count --show-mcdc
|
LL| |//@ llvm-cov-flags: --show-branches=count --show-mcdc
|
||||||
LL| |
|
LL| |
|
||||||
LL| |// Check that MC/DC instrumentation can gracefully handle conditions that
|
LL| 2|fn accept_7_conditions(bool_arr: [bool; 7]) {
|
||||||
LL| |// exceed LLVM's limit of 6 conditions per decision.
|
LL| 2| let [a, b, c, d, e, f, g] = bool_arr;
|
||||||
LL| |//
|
LL| 2| if a && b && c && d && e && f && g {
|
||||||
LL| |// (The limit is enforced in `compiler/rustc_mir_build/src/build/coverageinfo/mcdc.rs`.)
|
^1 ^1 ^1 ^1 ^1 ^1
|
||||||
LL| |
|
|
||||||
LL| 1|fn good() {
|
|
||||||
LL| 1| // With only 6 conditions, perform full MC/DC instrumentation.
|
|
||||||
LL| 1| let [a, b, c, d, e, f] = <[bool; 6]>::default();
|
|
||||||
LL| 1| if a && b && c && d && e && f {
|
|
||||||
^0 ^0 ^0 ^0 ^0
|
|
||||||
------------------
|
------------------
|
||||||
| Branch (LL:8): [True: 0, False: 1]
|
| Branch (LL:8): [True: 1, False: 1]
|
||||||
| Branch (LL:13): [True: 0, False: 0]
|
| Branch (LL:13): [True: 1, False: 0]
|
||||||
| Branch (LL:18): [True: 0, False: 0]
|
| Branch (LL:18): [True: 1, False: 0]
|
||||||
| Branch (LL:23): [True: 0, False: 0]
|
| Branch (LL:23): [True: 1, False: 0]
|
||||||
| Branch (LL:28): [True: 0, False: 0]
|
| Branch (LL:28): [True: 1, False: 0]
|
||||||
| Branch (LL:33): [True: 0, False: 0]
|
| Branch (LL:33): [True: 1, False: 0]
|
||||||
|
| Branch (LL:38): [True: 1, False: 0]
|
||||||
------------------
|
------------------
|
||||||
|---> MC/DC Decision Region (LL:8) to (LL:34)
|
|---> MC/DC Decision Region (LL:8) to (LL:39)
|
||||||
|
|
|
|
||||||
| Number of Conditions: 6
|
| Number of Conditions: 7
|
||||||
| Condition C1 --> (LL:8)
|
| Condition C1 --> (LL:8)
|
||||||
| Condition C2 --> (LL:13)
|
| Condition C2 --> (LL:13)
|
||||||
| Condition C3 --> (LL:18)
|
| Condition C3 --> (LL:18)
|
||||||
| Condition C4 --> (LL:23)
|
| Condition C4 --> (LL:23)
|
||||||
| Condition C5 --> (LL:28)
|
| Condition C5 --> (LL:28)
|
||||||
| Condition C6 --> (LL:33)
|
| Condition C6 --> (LL:33)
|
||||||
|
| Condition C7 --> (LL:38)
|
||||||
|
|
|
|
||||||
| Executed MC/DC Test Vectors:
|
| Executed MC/DC Test Vectors:
|
||||||
|
|
|
|
||||||
| C1, C2, C3, C4, C5, C6 Result
|
| C1, C2, C3, C4, C5, C6, C7 Result
|
||||||
| 1 { F, -, -, -, -, - = F }
|
| 1 { F, -, -, -, -, -, - = F }
|
||||||
|
| 2 { T, T, T, T, T, T, T = T }
|
||||||
|
|
|
|
||||||
| C1-Pair: not covered
|
| C1-Pair: covered: (1,2)
|
||||||
| C2-Pair: not covered
|
| C2-Pair: not covered
|
||||||
| C3-Pair: not covered
|
| C3-Pair: not covered
|
||||||
| C4-Pair: not covered
|
| C4-Pair: not covered
|
||||||
| C5-Pair: not covered
|
| C5-Pair: not covered
|
||||||
| C6-Pair: not covered
|
| C6-Pair: not covered
|
||||||
| MC/DC Coverage for Decision: 0.00%
|
| C7-Pair: not covered
|
||||||
|
| MC/DC Coverage for Decision: 14.29%
|
||||||
|
|
|
|
||||||
------------------
|
------------------
|
||||||
LL| 0| core::hint::black_box("hello");
|
LL| 1| core::hint::black_box("hello");
|
||||||
LL| 1| }
|
LL| 1| }
|
||||||
LL| 1|}
|
LL| 2|}
|
||||||
LL| |
|
|
||||||
LL| 1|fn bad() {
|
|
||||||
LL| 1| // With 7 conditions, fall back to branch instrumentation only.
|
|
||||||
LL| 1| let [a, b, c, d, e, f, g] = <[bool; 7]>::default();
|
|
||||||
LL| 1| if a && b && c && d && e && f && g {
|
|
||||||
^0 ^0 ^0 ^0 ^0 ^0
|
|
||||||
------------------
|
|
||||||
| Branch (LL:8): [True: 0, False: 1]
|
|
||||||
| Branch (LL:13): [True: 0, False: 0]
|
|
||||||
| Branch (LL:18): [True: 0, False: 0]
|
|
||||||
| Branch (LL:23): [True: 0, False: 0]
|
|
||||||
| Branch (LL:28): [True: 0, False: 0]
|
|
||||||
| Branch (LL:33): [True: 0, False: 0]
|
|
||||||
| Branch (LL:38): [True: 0, False: 0]
|
|
||||||
------------------
|
|
||||||
LL| 0| core::hint::black_box("hello");
|
|
||||||
LL| 1| }
|
|
||||||
LL| 1|}
|
|
||||||
LL| |
|
LL| |
|
||||||
LL| |#[coverage(off)]
|
LL| |#[coverage(off)]
|
||||||
LL| |fn main() {
|
LL| |fn main() {
|
||||||
LL| | good();
|
LL| | accept_7_conditions([false; 7]);
|
||||||
LL| | bad();
|
LL| | accept_7_conditions([true; 7]);
|
||||||
LL| |}
|
LL| |}
|
||||||
|
|
||||||
|
@ -1,25 +1,11 @@
|
|||||||
#![feature(coverage_attribute)]
|
#![feature(coverage_attribute)]
|
||||||
//@ edition: 2021
|
//@ edition: 2021
|
||||||
//@ ignore-llvm-version: 19 - 99
|
//@ min-llvm-version: 19
|
||||||
//@ compile-flags: -Zcoverage-options=mcdc
|
//@ compile-flags: -Zcoverage-options=mcdc
|
||||||
//@ llvm-cov-flags: --show-branches=count --show-mcdc
|
//@ llvm-cov-flags: --show-branches=count --show-mcdc
|
||||||
|
|
||||||
// Check that MC/DC instrumentation can gracefully handle conditions that
|
fn accept_7_conditions(bool_arr: [bool; 7]) {
|
||||||
// exceed LLVM's limit of 6 conditions per decision.
|
let [a, b, c, d, e, f, g] = bool_arr;
|
||||||
//
|
|
||||||
// (The limit is enforced in `compiler/rustc_mir_build/src/build/coverageinfo/mcdc.rs`.)
|
|
||||||
|
|
||||||
fn good() {
|
|
||||||
// With only 6 conditions, perform full MC/DC instrumentation.
|
|
||||||
let [a, b, c, d, e, f] = <[bool; 6]>::default();
|
|
||||||
if a && b && c && d && e && f {
|
|
||||||
core::hint::black_box("hello");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn bad() {
|
|
||||||
// With 7 conditions, fall back to branch instrumentation only.
|
|
||||||
let [a, b, c, d, e, f, g] = <[bool; 7]>::default();
|
|
||||||
if a && b && c && d && e && f && g {
|
if a && b && c && d && e && f && g {
|
||||||
core::hint::black_box("hello");
|
core::hint::black_box("hello");
|
||||||
}
|
}
|
||||||
@ -27,6 +13,6 @@ fn bad() {
|
|||||||
|
|
||||||
#[coverage(off)]
|
#[coverage(off)]
|
||||||
fn main() {
|
fn main() {
|
||||||
good();
|
accept_7_conditions([false; 7]);
|
||||||
bad();
|
accept_7_conditions([true; 7]);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
Function name: if::mcdc_check_a
|
Function name: if::mcdc_check_a
|
||||||
Raw bytes (64): 0x[01, 01, 04, 01, 05, 09, 02, 0d, 0f, 09, 02, 08, 01, 0f, 01, 01, 09, 28, 00, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 0e, 0d, 00, 0f, 02, 06, 0f, 02, 0c, 02, 06, 0b, 03, 01, 00, 02]
|
Raw bytes (64): 0x[01, 01, 04, 01, 05, 09, 02, 0d, 0f, 09, 02, 08, 01, 0f, 01, 01, 09, 28, 03, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 0e, 0d, 00, 0f, 02, 06, 0f, 02, 0c, 02, 06, 0b, 03, 01, 00, 02]
|
||||||
Number of files: 1
|
Number of files: 1
|
||||||
- file 0 => global file 1
|
- file 0 => global file 1
|
||||||
Number of expressions: 4
|
Number of expressions: 4
|
||||||
@ -9,7 +9,7 @@ Number of expressions: 4
|
|||||||
- expression 3 operands: lhs = Counter(2), rhs = Expression(0, Sub)
|
- expression 3 operands: lhs = Counter(2), rhs = Expression(0, Sub)
|
||||||
Number of file 0 mappings: 8
|
Number of file 0 mappings: 8
|
||||||
- Code(Counter(0)) at (prev + 15, 1) to (start + 1, 9)
|
- Code(Counter(0)) at (prev + 15, 1) to (start + 1, 9)
|
||||||
- MCDCDecision { bitmap_idx: 0, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 14)
|
- MCDCDecision { bitmap_idx: 3, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 14)
|
||||||
- MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9)
|
- MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9)
|
||||||
true = c1
|
true = c1
|
||||||
false = (c0 - c1)
|
false = (c0 - c1)
|
||||||
@ -24,7 +24,7 @@ Number of file 0 mappings: 8
|
|||||||
= (c3 + (c2 + (c0 - c1)))
|
= (c3 + (c2 + (c0 - c1)))
|
||||||
|
|
||||||
Function name: if::mcdc_check_b
|
Function name: if::mcdc_check_b
|
||||||
Raw bytes (64): 0x[01, 01, 04, 01, 05, 09, 02, 0d, 0f, 09, 02, 08, 01, 17, 01, 01, 09, 28, 00, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 0e, 0d, 00, 0f, 02, 06, 0f, 02, 0c, 02, 06, 0b, 03, 01, 00, 02]
|
Raw bytes (64): 0x[01, 01, 04, 01, 05, 09, 02, 0d, 0f, 09, 02, 08, 01, 17, 01, 01, 09, 28, 03, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 0e, 0d, 00, 0f, 02, 06, 0f, 02, 0c, 02, 06, 0b, 03, 01, 00, 02]
|
||||||
Number of files: 1
|
Number of files: 1
|
||||||
- file 0 => global file 1
|
- file 0 => global file 1
|
||||||
Number of expressions: 4
|
Number of expressions: 4
|
||||||
@ -34,7 +34,7 @@ Number of expressions: 4
|
|||||||
- expression 3 operands: lhs = Counter(2), rhs = Expression(0, Sub)
|
- expression 3 operands: lhs = Counter(2), rhs = Expression(0, Sub)
|
||||||
Number of file 0 mappings: 8
|
Number of file 0 mappings: 8
|
||||||
- Code(Counter(0)) at (prev + 23, 1) to (start + 1, 9)
|
- Code(Counter(0)) at (prev + 23, 1) to (start + 1, 9)
|
||||||
- MCDCDecision { bitmap_idx: 0, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 14)
|
- MCDCDecision { bitmap_idx: 3, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 14)
|
||||||
- MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9)
|
- MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9)
|
||||||
true = c1
|
true = c1
|
||||||
false = (c0 - c1)
|
false = (c0 - c1)
|
||||||
@ -49,7 +49,7 @@ Number of file 0 mappings: 8
|
|||||||
= (c3 + (c2 + (c0 - c1)))
|
= (c3 + (c2 + (c0 - c1)))
|
||||||
|
|
||||||
Function name: if::mcdc_check_both
|
Function name: if::mcdc_check_both
|
||||||
Raw bytes (64): 0x[01, 01, 04, 01, 05, 09, 02, 0d, 0f, 09, 02, 08, 01, 1f, 01, 01, 09, 28, 00, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 0e, 0d, 00, 0f, 02, 06, 0f, 02, 0c, 02, 06, 0b, 03, 01, 00, 02]
|
Raw bytes (64): 0x[01, 01, 04, 01, 05, 09, 02, 0d, 0f, 09, 02, 08, 01, 1f, 01, 01, 09, 28, 03, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 0e, 0d, 00, 0f, 02, 06, 0f, 02, 0c, 02, 06, 0b, 03, 01, 00, 02]
|
||||||
Number of files: 1
|
Number of files: 1
|
||||||
- file 0 => global file 1
|
- file 0 => global file 1
|
||||||
Number of expressions: 4
|
Number of expressions: 4
|
||||||
@ -59,7 +59,7 @@ Number of expressions: 4
|
|||||||
- expression 3 operands: lhs = Counter(2), rhs = Expression(0, Sub)
|
- expression 3 operands: lhs = Counter(2), rhs = Expression(0, Sub)
|
||||||
Number of file 0 mappings: 8
|
Number of file 0 mappings: 8
|
||||||
- Code(Counter(0)) at (prev + 31, 1) to (start + 1, 9)
|
- Code(Counter(0)) at (prev + 31, 1) to (start + 1, 9)
|
||||||
- MCDCDecision { bitmap_idx: 0, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 14)
|
- MCDCDecision { bitmap_idx: 3, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 14)
|
||||||
- MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9)
|
- MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9)
|
||||||
true = c1
|
true = c1
|
||||||
false = (c0 - c1)
|
false = (c0 - c1)
|
||||||
@ -74,7 +74,7 @@ Number of file 0 mappings: 8
|
|||||||
= (c3 + (c2 + (c0 - c1)))
|
= (c3 + (c2 + (c0 - c1)))
|
||||||
|
|
||||||
Function name: if::mcdc_check_neither
|
Function name: if::mcdc_check_neither
|
||||||
Raw bytes (64): 0x[01, 01, 04, 01, 05, 09, 02, 0d, 0f, 09, 02, 08, 01, 07, 01, 01, 09, 28, 00, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 0e, 0d, 00, 0f, 02, 06, 0f, 02, 0c, 02, 06, 0b, 03, 01, 00, 02]
|
Raw bytes (64): 0x[01, 01, 04, 01, 05, 09, 02, 0d, 0f, 09, 02, 08, 01, 07, 01, 01, 09, 28, 03, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 0e, 0d, 00, 0f, 02, 06, 0f, 02, 0c, 02, 06, 0b, 03, 01, 00, 02]
|
||||||
Number of files: 1
|
Number of files: 1
|
||||||
- file 0 => global file 1
|
- file 0 => global file 1
|
||||||
Number of expressions: 4
|
Number of expressions: 4
|
||||||
@ -84,7 +84,7 @@ Number of expressions: 4
|
|||||||
- expression 3 operands: lhs = Counter(2), rhs = Expression(0, Sub)
|
- expression 3 operands: lhs = Counter(2), rhs = Expression(0, Sub)
|
||||||
Number of file 0 mappings: 8
|
Number of file 0 mappings: 8
|
||||||
- Code(Counter(0)) at (prev + 7, 1) to (start + 1, 9)
|
- Code(Counter(0)) at (prev + 7, 1) to (start + 1, 9)
|
||||||
- MCDCDecision { bitmap_idx: 0, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 14)
|
- MCDCDecision { bitmap_idx: 3, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 14)
|
||||||
- MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9)
|
- MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9)
|
||||||
true = c1
|
true = c1
|
||||||
false = (c0 - c1)
|
false = (c0 - c1)
|
||||||
@ -99,7 +99,7 @@ Number of file 0 mappings: 8
|
|||||||
= (c3 + (c2 + (c0 - c1)))
|
= (c3 + (c2 + (c0 - c1)))
|
||||||
|
|
||||||
Function name: if::mcdc_check_not_tree_decision
|
Function name: if::mcdc_check_not_tree_decision
|
||||||
Raw bytes (87): 0x[01, 01, 08, 01, 05, 02, 09, 05, 09, 0d, 1e, 02, 09, 11, 1b, 0d, 1e, 02, 09, 0a, 01, 31, 01, 03, 0a, 28, 00, 03, 03, 08, 00, 15, 30, 05, 02, 01, 02, 03, 00, 09, 00, 0a, 02, 00, 0e, 00, 0f, 30, 09, 1e, 03, 02, 00, 00, 0e, 00, 0f, 0b, 00, 14, 00, 15, 30, 11, 0d, 02, 00, 00, 00, 14, 00, 15, 11, 00, 16, 02, 06, 1b, 02, 0c, 02, 06, 17, 03, 01, 00, 02]
|
Raw bytes (87): 0x[01, 01, 08, 01, 05, 02, 09, 05, 09, 0d, 1e, 02, 09, 11, 1b, 0d, 1e, 02, 09, 0a, 01, 31, 01, 03, 0a, 28, 05, 03, 03, 08, 00, 15, 30, 05, 02, 01, 02, 03, 00, 09, 00, 0a, 02, 00, 0e, 00, 0f, 30, 09, 1e, 03, 02, 00, 00, 0e, 00, 0f, 0b, 00, 14, 00, 15, 30, 11, 0d, 02, 00, 00, 00, 14, 00, 15, 11, 00, 16, 02, 06, 1b, 02, 0c, 02, 06, 17, 03, 01, 00, 02]
|
||||||
Number of files: 1
|
Number of files: 1
|
||||||
- file 0 => global file 1
|
- file 0 => global file 1
|
||||||
Number of expressions: 8
|
Number of expressions: 8
|
||||||
@ -113,7 +113,7 @@ Number of expressions: 8
|
|||||||
- expression 7 operands: lhs = Expression(0, Sub), rhs = Counter(2)
|
- expression 7 operands: lhs = Expression(0, Sub), rhs = Counter(2)
|
||||||
Number of file 0 mappings: 10
|
Number of file 0 mappings: 10
|
||||||
- Code(Counter(0)) at (prev + 49, 1) to (start + 3, 10)
|
- Code(Counter(0)) at (prev + 49, 1) to (start + 3, 10)
|
||||||
- MCDCDecision { bitmap_idx: 0, conditions_num: 3 } at (prev + 3, 8) to (start + 0, 21)
|
- MCDCDecision { bitmap_idx: 5, conditions_num: 3 } at (prev + 3, 8) to (start + 0, 21)
|
||||||
- MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 3 } at (prev + 0, 9) to (start + 0, 10)
|
- MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 3 } at (prev + 0, 9) to (start + 0, 10)
|
||||||
true = c1
|
true = c1
|
||||||
false = (c0 - c1)
|
false = (c0 - c1)
|
||||||
@ -134,7 +134,7 @@ Number of file 0 mappings: 10
|
|||||||
= (c4 + (c3 + ((c0 - c1) - c2)))
|
= (c4 + (c3 + ((c0 - c1) - c2)))
|
||||||
|
|
||||||
Function name: if::mcdc_check_tree_decision
|
Function name: if::mcdc_check_tree_decision
|
||||||
Raw bytes (87): 0x[01, 01, 08, 01, 05, 05, 0d, 05, 0d, 0d, 11, 09, 02, 1b, 1f, 0d, 11, 09, 02, 0a, 01, 27, 01, 03, 09, 28, 00, 03, 03, 08, 00, 15, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0e, 00, 0f, 30, 0d, 0a, 02, 00, 03, 00, 0e, 00, 0f, 0a, 00, 13, 00, 14, 30, 11, 09, 03, 00, 00, 00, 13, 00, 14, 1b, 00, 16, 02, 06, 1f, 02, 0c, 02, 06, 17, 03, 01, 00, 02]
|
Raw bytes (87): 0x[01, 01, 08, 01, 05, 05, 0d, 05, 0d, 0d, 11, 09, 02, 1b, 1f, 0d, 11, 09, 02, 0a, 01, 27, 01, 03, 09, 28, 04, 03, 03, 08, 00, 15, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0e, 00, 0f, 30, 0d, 0a, 02, 00, 03, 00, 0e, 00, 0f, 0a, 00, 13, 00, 14, 30, 11, 09, 03, 00, 00, 00, 13, 00, 14, 1b, 00, 16, 02, 06, 1f, 02, 0c, 02, 06, 17, 03, 01, 00, 02]
|
||||||
Number of files: 1
|
Number of files: 1
|
||||||
- file 0 => global file 1
|
- file 0 => global file 1
|
||||||
Number of expressions: 8
|
Number of expressions: 8
|
||||||
@ -148,7 +148,7 @@ Number of expressions: 8
|
|||||||
- expression 7 operands: lhs = Counter(2), rhs = Expression(0, Sub)
|
- expression 7 operands: lhs = Counter(2), rhs = Expression(0, Sub)
|
||||||
Number of file 0 mappings: 10
|
Number of file 0 mappings: 10
|
||||||
- Code(Counter(0)) at (prev + 39, 1) to (start + 3, 9)
|
- Code(Counter(0)) at (prev + 39, 1) to (start + 3, 9)
|
||||||
- MCDCDecision { bitmap_idx: 0, conditions_num: 3 } at (prev + 3, 8) to (start + 0, 21)
|
- MCDCDecision { bitmap_idx: 4, conditions_num: 3 } at (prev + 3, 8) to (start + 0, 21)
|
||||||
- MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9)
|
- MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9)
|
||||||
true = c1
|
true = c1
|
||||||
false = (c0 - c1)
|
false = (c0 - c1)
|
||||||
@ -169,7 +169,7 @@ Number of file 0 mappings: 10
|
|||||||
= ((c3 + c4) + (c2 + (c0 - c1)))
|
= ((c3 + c4) + (c2 + (c0 - c1)))
|
||||||
|
|
||||||
Function name: if::mcdc_nested_if
|
Function name: if::mcdc_nested_if
|
||||||
Raw bytes (124): 0x[01, 01, 0d, 01, 05, 02, 09, 05, 09, 1b, 15, 05, 09, 1b, 15, 05, 09, 11, 15, 02, 09, 2b, 32, 0d, 2f, 11, 15, 02, 09, 0e, 01, 3b, 01, 01, 09, 28, 00, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 00, 02, 00, 08, 00, 09, 02, 00, 0d, 00, 0e, 30, 09, 32, 02, 00, 00, 00, 0d, 00, 0e, 1b, 01, 09, 01, 0d, 28, 01, 02, 01, 0c, 00, 12, 30, 16, 15, 01, 02, 00, 00, 0c, 00, 0d, 16, 00, 11, 00, 12, 30, 0d, 11, 02, 00, 00, 00, 11, 00, 12, 0d, 00, 13, 02, 0a, 2f, 02, 0a, 00, 0b, 32, 01, 0c, 02, 06, 27, 03, 01, 00, 02]
|
Raw bytes (124): 0x[01, 01, 0d, 01, 05, 02, 09, 05, 09, 1b, 15, 05, 09, 1b, 15, 05, 09, 11, 15, 02, 09, 2b, 32, 0d, 2f, 11, 15, 02, 09, 0e, 01, 3b, 01, 01, 09, 28, 03, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 00, 02, 00, 08, 00, 09, 02, 00, 0d, 00, 0e, 30, 09, 32, 02, 00, 00, 00, 0d, 00, 0e, 1b, 01, 09, 01, 0d, 28, 06, 02, 01, 0c, 00, 12, 30, 16, 15, 01, 02, 00, 00, 0c, 00, 0d, 16, 00, 11, 00, 12, 30, 0d, 11, 02, 00, 00, 00, 11, 00, 12, 0d, 00, 13, 02, 0a, 2f, 02, 0a, 00, 0b, 32, 01, 0c, 02, 06, 27, 03, 01, 00, 02]
|
||||||
Number of files: 1
|
Number of files: 1
|
||||||
- file 0 => global file 1
|
- file 0 => global file 1
|
||||||
Number of expressions: 13
|
Number of expressions: 13
|
||||||
@ -188,7 +188,7 @@ Number of expressions: 13
|
|||||||
- expression 12 operands: lhs = Expression(0, Sub), rhs = Counter(2)
|
- expression 12 operands: lhs = Expression(0, Sub), rhs = Counter(2)
|
||||||
Number of file 0 mappings: 14
|
Number of file 0 mappings: 14
|
||||||
- Code(Counter(0)) at (prev + 59, 1) to (start + 1, 9)
|
- Code(Counter(0)) at (prev + 59, 1) to (start + 1, 9)
|
||||||
- MCDCDecision { bitmap_idx: 0, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 14)
|
- MCDCDecision { bitmap_idx: 3, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 14)
|
||||||
- MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 0, false_next_id: 2 } at (prev + 0, 8) to (start + 0, 9)
|
- MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 0, false_next_id: 2 } at (prev + 0, 8) to (start + 0, 9)
|
||||||
true = c1
|
true = c1
|
||||||
false = (c0 - c1)
|
false = (c0 - c1)
|
||||||
@ -199,7 +199,7 @@ Number of file 0 mappings: 14
|
|||||||
false = ((c0 - c1) - c2)
|
false = ((c0 - c1) - c2)
|
||||||
- Code(Expression(6, Add)) at (prev + 1, 9) to (start + 1, 13)
|
- Code(Expression(6, Add)) at (prev + 1, 9) to (start + 1, 13)
|
||||||
= (c1 + c2)
|
= (c1 + c2)
|
||||||
- MCDCDecision { bitmap_idx: 1, conditions_num: 2 } at (prev + 1, 12) to (start + 0, 18)
|
- MCDCDecision { bitmap_idx: 6, conditions_num: 2 } at (prev + 1, 12) to (start + 0, 18)
|
||||||
- MCDCBranch { true: Expression(5, Sub), false: Counter(5), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 12) to (start + 0, 13)
|
- MCDCBranch { true: Expression(5, Sub), false: Counter(5), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 12) to (start + 0, 13)
|
||||||
true = ((c1 + c2) - c5)
|
true = ((c1 + c2) - c5)
|
||||||
false = c5
|
false = c5
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
LL| |#![feature(coverage_attribute)]
|
LL| |#![feature(coverage_attribute)]
|
||||||
LL| |//@ edition: 2021
|
LL| |//@ edition: 2021
|
||||||
LL| |//@ ignore-llvm-version: 19 - 99
|
LL| |//@ min-llvm-version: 19
|
||||||
LL| |//@ compile-flags: -Zcoverage-options=mcdc
|
LL| |//@ compile-flags: -Zcoverage-options=mcdc
|
||||||
LL| |//@ llvm-cov-flags: --show-branches=count --show-mcdc
|
LL| |//@ llvm-cov-flags: --show-branches=count --show-mcdc
|
||||||
LL| |
|
LL| |
|
||||||
@ -145,12 +145,12 @@
|
|||||||
| C1, C2, C3 Result
|
| C1, C2, C3 Result
|
||||||
| 1 { F, -, - = F }
|
| 1 { F, -, - = F }
|
||||||
| 2 { T, F, F = F }
|
| 2 { T, F, F = F }
|
||||||
| 3 { T, T, - = T }
|
| 3 { T, F, T = T }
|
||||||
| 4 { T, F, T = T }
|
| 4 { T, T, - = T }
|
||||||
|
|
|
|
||||||
| C1-Pair: covered: (1,3)
|
| C1-Pair: covered: (1,3)
|
||||||
| C2-Pair: covered: (2,3)
|
| C2-Pair: covered: (2,4)
|
||||||
| C3-Pair: covered: (2,4)
|
| C3-Pair: covered: (2,3)
|
||||||
| MC/DC Coverage for Decision: 100.00%
|
| MC/DC Coverage for Decision: 100.00%
|
||||||
|
|
|
|
||||||
------------------
|
------------------
|
||||||
@ -162,7 +162,7 @@
|
|||||||
LL| |
|
LL| |
|
||||||
LL| 4|fn mcdc_check_not_tree_decision(a: bool, b: bool, c: bool) {
|
LL| 4|fn mcdc_check_not_tree_decision(a: bool, b: bool, c: bool) {
|
||||||
LL| 4| // Contradict to `mcdc_check_tree_decision`,
|
LL| 4| // Contradict to `mcdc_check_tree_decision`,
|
||||||
LL| 4| // 100% branch coverage of this expression does not mean indicates 100% mcdc coverage.
|
LL| 4| // 100% branch coverage of this expression does not indicate 100% mcdc coverage.
|
||||||
LL| 4| if (a || b) && c {
|
LL| 4| if (a || b) && c {
|
||||||
^1
|
^1
|
||||||
------------------
|
------------------
|
||||||
@ -181,12 +181,12 @@
|
|||||||
|
|
|
|
||||||
| C1, C2, C3 Result
|
| C1, C2, C3 Result
|
||||||
| 1 { T, -, F = F }
|
| 1 { T, -, F = F }
|
||||||
| 2 { T, -, T = T }
|
| 2 { F, T, T = T }
|
||||||
| 3 { F, T, T = T }
|
| 3 { T, -, T = T }
|
||||||
|
|
|
|
||||||
| C1-Pair: not covered
|
| C1-Pair: not covered
|
||||||
| C2-Pair: not covered
|
| C2-Pair: not covered
|
||||||
| C3-Pair: covered: (1,2)
|
| C3-Pair: covered: (1,3)
|
||||||
| MC/DC Coverage for Decision: 33.33%
|
| MC/DC Coverage for Decision: 33.33%
|
||||||
|
|
|
|
||||||
------------------
|
------------------
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#![feature(coverage_attribute)]
|
#![feature(coverage_attribute)]
|
||||||
//@ edition: 2021
|
//@ edition: 2021
|
||||||
//@ ignore-llvm-version: 19 - 99
|
//@ min-llvm-version: 19
|
||||||
//@ compile-flags: -Zcoverage-options=mcdc
|
//@ compile-flags: -Zcoverage-options=mcdc
|
||||||
//@ llvm-cov-flags: --show-branches=count --show-mcdc
|
//@ llvm-cov-flags: --show-branches=count --show-mcdc
|
||||||
|
|
||||||
@ -48,7 +48,7 @@ fn mcdc_check_tree_decision(a: bool, b: bool, c: bool) {
|
|||||||
|
|
||||||
fn mcdc_check_not_tree_decision(a: bool, b: bool, c: bool) {
|
fn mcdc_check_not_tree_decision(a: bool, b: bool, c: bool) {
|
||||||
// Contradict to `mcdc_check_tree_decision`,
|
// Contradict to `mcdc_check_tree_decision`,
|
||||||
// 100% branch coverage of this expression does not mean indicates 100% mcdc coverage.
|
// 100% branch coverage of this expression does not indicate 100% mcdc coverage.
|
||||||
if (a || b) && c {
|
if (a || b) && c {
|
||||||
say("pass");
|
say("pass");
|
||||||
} else {
|
} else {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
Function name: inlined_expressions::inlined_instance
|
Function name: inlined_expressions::inlined_instance
|
||||||
Raw bytes (52): 0x[01, 01, 03, 01, 05, 0b, 02, 09, 0d, 06, 01, 08, 01, 01, 06, 28, 00, 02, 01, 05, 00, 0b, 30, 05, 02, 01, 02, 00, 00, 05, 00, 06, 05, 00, 0a, 00, 0b, 30, 09, 0d, 02, 00, 00, 00, 0a, 00, 0b, 07, 01, 01, 00, 02]
|
Raw bytes (52): 0x[01, 01, 03, 01, 05, 0b, 02, 09, 0d, 06, 01, 08, 01, 01, 06, 28, 03, 02, 01, 05, 00, 0b, 30, 05, 02, 01, 02, 00, 00, 05, 00, 06, 05, 00, 0a, 00, 0b, 30, 09, 0d, 02, 00, 00, 00, 0a, 00, 0b, 07, 01, 01, 00, 02]
|
||||||
Number of files: 1
|
Number of files: 1
|
||||||
- file 0 => global file 1
|
- file 0 => global file 1
|
||||||
Number of expressions: 3
|
Number of expressions: 3
|
||||||
@ -8,7 +8,7 @@ Number of expressions: 3
|
|||||||
- expression 2 operands: lhs = Counter(2), rhs = Counter(3)
|
- expression 2 operands: lhs = Counter(2), rhs = Counter(3)
|
||||||
Number of file 0 mappings: 6
|
Number of file 0 mappings: 6
|
||||||
- Code(Counter(0)) at (prev + 8, 1) to (start + 1, 6)
|
- Code(Counter(0)) at (prev + 8, 1) to (start + 1, 6)
|
||||||
- MCDCDecision { bitmap_idx: 0, conditions_num: 2 } at (prev + 1, 5) to (start + 0, 11)
|
- MCDCDecision { bitmap_idx: 3, conditions_num: 2 } at (prev + 1, 5) to (start + 0, 11)
|
||||||
- MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 5) to (start + 0, 6)
|
- MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 5) to (start + 0, 6)
|
||||||
true = c1
|
true = c1
|
||||||
false = (c0 - c1)
|
false = (c0 - c1)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
LL| |#![feature(coverage_attribute)]
|
LL| |#![feature(coverage_attribute)]
|
||||||
LL| |//@ edition: 2021
|
LL| |//@ edition: 2021
|
||||||
LL| |//@ ignore-llvm-version: 19 - 99
|
LL| |//@ min-llvm-version: 19
|
||||||
LL| |//@ compile-flags: -Zcoverage-options=mcdc -Copt-level=z -Cllvm-args=--inline-threshold=0
|
LL| |//@ compile-flags: -Zcoverage-options=mcdc -Copt-level=z -Cllvm-args=--inline-threshold=0
|
||||||
LL| |//@ llvm-cov-flags: --show-branches=count --show-mcdc
|
LL| |//@ llvm-cov-flags: --show-branches=count --show-mcdc
|
||||||
LL| |
|
LL| |
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#![feature(coverage_attribute)]
|
#![feature(coverage_attribute)]
|
||||||
//@ edition: 2021
|
//@ edition: 2021
|
||||||
//@ ignore-llvm-version: 19 - 99
|
//@ min-llvm-version: 19
|
||||||
//@ compile-flags: -Zcoverage-options=mcdc -Copt-level=z -Cllvm-args=--inline-threshold=0
|
//@ compile-flags: -Zcoverage-options=mcdc -Copt-level=z -Cllvm-args=--inline-threshold=0
|
||||||
//@ llvm-cov-flags: --show-branches=count --show-mcdc
|
//@ llvm-cov-flags: --show-branches=count --show-mcdc
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
Function name: nested_if::doubly_nested_if_in_condition
|
Function name: nested_if::doubly_nested_if_in_condition
|
||||||
Raw bytes (168): 0x[01, 01, 0e, 01, 05, 05, 11, 05, 11, 26, 19, 05, 11, 19, 1d, 19, 1d, 1d, 22, 26, 19, 05, 11, 11, 15, 09, 02, 0d, 37, 09, 02, 14, 01, 0f, 01, 01, 09, 28, 02, 02, 01, 08, 00, 4e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 4e, 05, 00, 10, 00, 11, 28, 01, 02, 00, 10, 00, 36, 30, 11, 26, 01, 00, 02, 00, 10, 00, 11, 30, 15, 21, 02, 00, 00, 00, 15, 00, 36, 26, 00, 18, 00, 19, 28, 00, 02, 00, 18, 00, 1e, 30, 19, 22, 01, 02, 00, 00, 18, 00, 19, 19, 00, 1d, 00, 1e, 30, 1a, 1d, 02, 00, 00, 00, 1d, 00, 1e, 1a, 00, 21, 00, 25, 1f, 00, 2f, 00, 34, 2b, 00, 39, 00, 3e, 21, 00, 48, 00, 4c, 0d, 00, 4f, 02, 06, 37, 02, 0c, 02, 06, 33, 03, 01, 00, 02]
|
Raw bytes (168): 0x[01, 01, 0e, 01, 05, 05, 11, 05, 11, 26, 19, 05, 11, 19, 1d, 19, 1d, 1d, 22, 26, 19, 05, 11, 11, 15, 09, 02, 0d, 37, 09, 02, 14, 01, 0f, 01, 01, 09, 28, 09, 02, 01, 08, 00, 4e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 4e, 05, 00, 10, 00, 11, 28, 06, 02, 00, 10, 00, 36, 30, 11, 26, 01, 00, 02, 00, 10, 00, 11, 30, 15, 21, 02, 00, 00, 00, 15, 00, 36, 26, 00, 18, 00, 19, 28, 03, 02, 00, 18, 00, 1e, 30, 19, 22, 01, 02, 00, 00, 18, 00, 19, 19, 00, 1d, 00, 1e, 30, 1a, 1d, 02, 00, 00, 00, 1d, 00, 1e, 1a, 00, 21, 00, 25, 1f, 00, 2f, 00, 34, 2b, 00, 39, 00, 3e, 21, 00, 48, 00, 4c, 0d, 00, 4f, 02, 06, 37, 02, 0c, 02, 06, 33, 03, 01, 00, 02]
|
||||||
Number of files: 1
|
Number of files: 1
|
||||||
- file 0 => global file 1
|
- file 0 => global file 1
|
||||||
Number of expressions: 14
|
Number of expressions: 14
|
||||||
@ -19,7 +19,7 @@ Number of expressions: 14
|
|||||||
- expression 13 operands: lhs = Counter(2), rhs = Expression(0, Sub)
|
- expression 13 operands: lhs = Counter(2), rhs = Expression(0, Sub)
|
||||||
Number of file 0 mappings: 20
|
Number of file 0 mappings: 20
|
||||||
- Code(Counter(0)) at (prev + 15, 1) to (start + 1, 9)
|
- Code(Counter(0)) at (prev + 15, 1) to (start + 1, 9)
|
||||||
- MCDCDecision { bitmap_idx: 2, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 78)
|
- MCDCDecision { bitmap_idx: 9, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 78)
|
||||||
- MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9)
|
- MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9)
|
||||||
true = c1
|
true = c1
|
||||||
false = (c0 - c1)
|
false = (c0 - c1)
|
||||||
@ -27,7 +27,7 @@ Number of file 0 mappings: 20
|
|||||||
true = c3
|
true = c3
|
||||||
false = c2
|
false = c2
|
||||||
- Code(Counter(1)) at (prev + 0, 16) to (start + 0, 17)
|
- Code(Counter(1)) at (prev + 0, 16) to (start + 0, 17)
|
||||||
- MCDCDecision { bitmap_idx: 1, conditions_num: 2 } at (prev + 0, 16) to (start + 0, 54)
|
- MCDCDecision { bitmap_idx: 6, conditions_num: 2 } at (prev + 0, 16) to (start + 0, 54)
|
||||||
- MCDCBranch { true: Counter(4), false: Expression(9, Sub), condition_id: 1, true_next_id: 0, false_next_id: 2 } at (prev + 0, 16) to (start + 0, 17)
|
- MCDCBranch { true: Counter(4), false: Expression(9, Sub), condition_id: 1, true_next_id: 0, false_next_id: 2 } at (prev + 0, 16) to (start + 0, 17)
|
||||||
true = c4
|
true = c4
|
||||||
false = (c1 - c4)
|
false = (c1 - c4)
|
||||||
@ -36,7 +36,7 @@ Number of file 0 mappings: 20
|
|||||||
false = c8
|
false = c8
|
||||||
- Code(Expression(9, Sub)) at (prev + 0, 24) to (start + 0, 25)
|
- Code(Expression(9, Sub)) at (prev + 0, 24) to (start + 0, 25)
|
||||||
= (c1 - c4)
|
= (c1 - c4)
|
||||||
- MCDCDecision { bitmap_idx: 0, conditions_num: 2 } at (prev + 0, 24) to (start + 0, 30)
|
- MCDCDecision { bitmap_idx: 3, conditions_num: 2 } at (prev + 0, 24) to (start + 0, 30)
|
||||||
- MCDCBranch { true: Counter(6), false: Expression(8, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 24) to (start + 0, 25)
|
- MCDCBranch { true: Counter(6), false: Expression(8, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 24) to (start + 0, 25)
|
||||||
true = c6
|
true = c6
|
||||||
false = ((c1 - c4) - c6)
|
false = ((c1 - c4) - c6)
|
||||||
@ -58,7 +58,7 @@ Number of file 0 mappings: 20
|
|||||||
= (c3 + (c2 + (c0 - c1)))
|
= (c3 + (c2 + (c0 - c1)))
|
||||||
|
|
||||||
Function name: nested_if::nested_if_in_condition
|
Function name: nested_if::nested_if_in_condition
|
||||||
Raw bytes (120): 0x[01, 01, 0b, 01, 05, 05, 11, 05, 11, 1e, 15, 05, 11, 11, 15, 1e, 15, 05, 11, 09, 02, 0d, 2b, 09, 02, 0e, 01, 07, 01, 01, 09, 28, 01, 02, 01, 08, 00, 2e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 2e, 05, 00, 10, 00, 11, 28, 00, 02, 00, 10, 00, 16, 30, 11, 1e, 01, 00, 02, 00, 10, 00, 11, 1e, 00, 15, 00, 16, 30, 15, 1a, 02, 00, 00, 00, 15, 00, 16, 17, 00, 19, 00, 1d, 1a, 00, 27, 00, 2c, 0d, 00, 2f, 02, 06, 2b, 02, 0c, 02, 06, 27, 03, 01, 00, 02]
|
Raw bytes (120): 0x[01, 01, 0b, 01, 05, 05, 11, 05, 11, 1e, 15, 05, 11, 11, 15, 1e, 15, 05, 11, 09, 02, 0d, 2b, 09, 02, 0e, 01, 07, 01, 01, 09, 28, 06, 02, 01, 08, 00, 2e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 2e, 05, 00, 10, 00, 11, 28, 03, 02, 00, 10, 00, 16, 30, 11, 1e, 01, 00, 02, 00, 10, 00, 11, 1e, 00, 15, 00, 16, 30, 15, 1a, 02, 00, 00, 00, 15, 00, 16, 17, 00, 19, 00, 1d, 1a, 00, 27, 00, 2c, 0d, 00, 2f, 02, 06, 2b, 02, 0c, 02, 06, 27, 03, 01, 00, 02]
|
||||||
Number of files: 1
|
Number of files: 1
|
||||||
- file 0 => global file 1
|
- file 0 => global file 1
|
||||||
Number of expressions: 11
|
Number of expressions: 11
|
||||||
@ -75,7 +75,7 @@ Number of expressions: 11
|
|||||||
- expression 10 operands: lhs = Counter(2), rhs = Expression(0, Sub)
|
- expression 10 operands: lhs = Counter(2), rhs = Expression(0, Sub)
|
||||||
Number of file 0 mappings: 14
|
Number of file 0 mappings: 14
|
||||||
- Code(Counter(0)) at (prev + 7, 1) to (start + 1, 9)
|
- Code(Counter(0)) at (prev + 7, 1) to (start + 1, 9)
|
||||||
- MCDCDecision { bitmap_idx: 1, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 46)
|
- MCDCDecision { bitmap_idx: 6, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 46)
|
||||||
- MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9)
|
- MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9)
|
||||||
true = c1
|
true = c1
|
||||||
false = (c0 - c1)
|
false = (c0 - c1)
|
||||||
@ -83,7 +83,7 @@ Number of file 0 mappings: 14
|
|||||||
true = c3
|
true = c3
|
||||||
false = c2
|
false = c2
|
||||||
- Code(Counter(1)) at (prev + 0, 16) to (start + 0, 17)
|
- Code(Counter(1)) at (prev + 0, 16) to (start + 0, 17)
|
||||||
- MCDCDecision { bitmap_idx: 0, conditions_num: 2 } at (prev + 0, 16) to (start + 0, 22)
|
- MCDCDecision { bitmap_idx: 3, conditions_num: 2 } at (prev + 0, 16) to (start + 0, 22)
|
||||||
- MCDCBranch { true: Counter(4), false: Expression(7, Sub), condition_id: 1, true_next_id: 0, false_next_id: 2 } at (prev + 0, 16) to (start + 0, 17)
|
- MCDCBranch { true: Counter(4), false: Expression(7, Sub), condition_id: 1, true_next_id: 0, false_next_id: 2 } at (prev + 0, 16) to (start + 0, 17)
|
||||||
true = c4
|
true = c4
|
||||||
false = (c1 - c4)
|
false = (c1 - c4)
|
||||||
@ -103,7 +103,7 @@ Number of file 0 mappings: 14
|
|||||||
= (c3 + (c2 + (c0 - c1)))
|
= (c3 + (c2 + (c0 - c1)))
|
||||||
|
|
||||||
Function name: nested_if::nested_in_then_block_in_condition
|
Function name: nested_if::nested_in_then_block_in_condition
|
||||||
Raw bytes (176): 0x[01, 01, 12, 01, 05, 05, 11, 05, 11, 3a, 15, 05, 11, 11, 15, 33, 19, 11, 15, 19, 1d, 19, 1d, 1d, 2e, 33, 19, 11, 15, 3a, 15, 05, 11, 09, 02, 0d, 47, 09, 02, 14, 01, 22, 01, 01, 09, 28, 02, 02, 01, 08, 00, 4b, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 4b, 05, 00, 10, 00, 11, 28, 00, 02, 00, 10, 00, 16, 30, 11, 3a, 01, 00, 02, 00, 10, 00, 11, 3a, 00, 15, 00, 16, 30, 15, 36, 02, 00, 00, 00, 15, 00, 16, 33, 00, 1c, 00, 1d, 28, 01, 02, 00, 1c, 00, 22, 30, 19, 2e, 01, 02, 00, 00, 1c, 00, 1d, 19, 00, 21, 00, 22, 30, 26, 1d, 02, 00, 00, 00, 21, 00, 22, 26, 00, 25, 00, 29, 2b, 00, 33, 00, 38, 36, 00, 44, 00, 49, 0d, 00, 4c, 02, 06, 47, 02, 0c, 02, 06, 43, 03, 01, 00, 02]
|
Raw bytes (176): 0x[01, 01, 12, 01, 05, 05, 11, 05, 11, 3a, 15, 05, 11, 11, 15, 33, 19, 11, 15, 19, 1d, 19, 1d, 1d, 2e, 33, 19, 11, 15, 3a, 15, 05, 11, 09, 02, 0d, 47, 09, 02, 14, 01, 22, 01, 01, 09, 28, 09, 02, 01, 08, 00, 4b, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 4b, 05, 00, 10, 00, 11, 28, 03, 02, 00, 10, 00, 16, 30, 11, 3a, 01, 00, 02, 00, 10, 00, 11, 3a, 00, 15, 00, 16, 30, 15, 36, 02, 00, 00, 00, 15, 00, 16, 33, 00, 1c, 00, 1d, 28, 06, 02, 00, 1c, 00, 22, 30, 19, 2e, 01, 02, 00, 00, 1c, 00, 1d, 19, 00, 21, 00, 22, 30, 26, 1d, 02, 00, 00, 00, 21, 00, 22, 26, 00, 25, 00, 29, 2b, 00, 33, 00, 38, 36, 00, 44, 00, 49, 0d, 00, 4c, 02, 06, 47, 02, 0c, 02, 06, 43, 03, 01, 00, 02]
|
||||||
Number of files: 1
|
Number of files: 1
|
||||||
- file 0 => global file 1
|
- file 0 => global file 1
|
||||||
Number of expressions: 18
|
Number of expressions: 18
|
||||||
@ -127,7 +127,7 @@ Number of expressions: 18
|
|||||||
- expression 17 operands: lhs = Counter(2), rhs = Expression(0, Sub)
|
- expression 17 operands: lhs = Counter(2), rhs = Expression(0, Sub)
|
||||||
Number of file 0 mappings: 20
|
Number of file 0 mappings: 20
|
||||||
- Code(Counter(0)) at (prev + 34, 1) to (start + 1, 9)
|
- Code(Counter(0)) at (prev + 34, 1) to (start + 1, 9)
|
||||||
- MCDCDecision { bitmap_idx: 2, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 75)
|
- MCDCDecision { bitmap_idx: 9, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 75)
|
||||||
- MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9)
|
- MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9)
|
||||||
true = c1
|
true = c1
|
||||||
false = (c0 - c1)
|
false = (c0 - c1)
|
||||||
@ -135,7 +135,7 @@ Number of file 0 mappings: 20
|
|||||||
true = c3
|
true = c3
|
||||||
false = c2
|
false = c2
|
||||||
- Code(Counter(1)) at (prev + 0, 16) to (start + 0, 17)
|
- Code(Counter(1)) at (prev + 0, 16) to (start + 0, 17)
|
||||||
- MCDCDecision { bitmap_idx: 0, conditions_num: 2 } at (prev + 0, 16) to (start + 0, 22)
|
- MCDCDecision { bitmap_idx: 3, conditions_num: 2 } at (prev + 0, 16) to (start + 0, 22)
|
||||||
- MCDCBranch { true: Counter(4), false: Expression(14, Sub), condition_id: 1, true_next_id: 0, false_next_id: 2 } at (prev + 0, 16) to (start + 0, 17)
|
- MCDCBranch { true: Counter(4), false: Expression(14, Sub), condition_id: 1, true_next_id: 0, false_next_id: 2 } at (prev + 0, 16) to (start + 0, 17)
|
||||||
true = c4
|
true = c4
|
||||||
false = (c1 - c4)
|
false = (c1 - c4)
|
||||||
@ -146,7 +146,7 @@ Number of file 0 mappings: 20
|
|||||||
false = ((c1 - c4) - c5)
|
false = ((c1 - c4) - c5)
|
||||||
- Code(Expression(12, Add)) at (prev + 0, 28) to (start + 0, 29)
|
- Code(Expression(12, Add)) at (prev + 0, 28) to (start + 0, 29)
|
||||||
= (c4 + c5)
|
= (c4 + c5)
|
||||||
- MCDCDecision { bitmap_idx: 1, conditions_num: 2 } at (prev + 0, 28) to (start + 0, 34)
|
- MCDCDecision { bitmap_idx: 6, conditions_num: 2 } at (prev + 0, 28) to (start + 0, 34)
|
||||||
- MCDCBranch { true: Counter(6), false: Expression(11, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 28) to (start + 0, 29)
|
- MCDCBranch { true: Counter(6), false: Expression(11, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 28) to (start + 0, 29)
|
||||||
true = c6
|
true = c6
|
||||||
false = ((c4 + c5) - c6)
|
false = ((c4 + c5) - c6)
|
||||||
@ -167,7 +167,7 @@ Number of file 0 mappings: 20
|
|||||||
= (c3 + (c2 + (c0 - c1)))
|
= (c3 + (c2 + (c0 - c1)))
|
||||||
|
|
||||||
Function name: nested_if::nested_single_condition_decision
|
Function name: nested_if::nested_single_condition_decision
|
||||||
Raw bytes (85): 0x[01, 01, 06, 01, 05, 05, 11, 05, 11, 09, 02, 0d, 17, 09, 02, 0b, 01, 17, 01, 04, 09, 28, 00, 02, 04, 08, 00, 29, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 29, 05, 00, 10, 00, 11, 20, 11, 0a, 00, 10, 00, 11, 11, 00, 14, 00, 19, 0a, 00, 23, 00, 27, 0d, 00, 2a, 02, 06, 17, 02, 0c, 02, 06, 13, 03, 01, 00, 02]
|
Raw bytes (85): 0x[01, 01, 06, 01, 05, 05, 11, 05, 11, 09, 02, 0d, 17, 09, 02, 0b, 01, 17, 01, 04, 09, 28, 03, 02, 04, 08, 00, 29, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 29, 05, 00, 10, 00, 11, 20, 11, 0a, 00, 10, 00, 11, 11, 00, 14, 00, 19, 0a, 00, 23, 00, 27, 0d, 00, 2a, 02, 06, 17, 02, 0c, 02, 06, 13, 03, 01, 00, 02]
|
||||||
Number of files: 1
|
Number of files: 1
|
||||||
- file 0 => global file 1
|
- file 0 => global file 1
|
||||||
Number of expressions: 6
|
Number of expressions: 6
|
||||||
@ -179,7 +179,7 @@ Number of expressions: 6
|
|||||||
- expression 5 operands: lhs = Counter(2), rhs = Expression(0, Sub)
|
- expression 5 operands: lhs = Counter(2), rhs = Expression(0, Sub)
|
||||||
Number of file 0 mappings: 11
|
Number of file 0 mappings: 11
|
||||||
- Code(Counter(0)) at (prev + 23, 1) to (start + 4, 9)
|
- Code(Counter(0)) at (prev + 23, 1) to (start + 4, 9)
|
||||||
- MCDCDecision { bitmap_idx: 0, conditions_num: 2 } at (prev + 4, 8) to (start + 0, 41)
|
- MCDCDecision { bitmap_idx: 3, conditions_num: 2 } at (prev + 4, 8) to (start + 0, 41)
|
||||||
- MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9)
|
- MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9)
|
||||||
true = c1
|
true = c1
|
||||||
false = (c0 - c1)
|
false = (c0 - c1)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
LL| |#![feature(coverage_attribute)]
|
LL| |#![feature(coverage_attribute)]
|
||||||
LL| |//@ edition: 2021
|
LL| |//@ edition: 2021
|
||||||
LL| |//@ ignore-llvm-version: 19 - 99
|
LL| |//@ min-llvm-version: 19
|
||||||
LL| |//@ compile-flags: -Zcoverage-options=mcdc
|
LL| |//@ compile-flags: -Zcoverage-options=mcdc
|
||||||
LL| |//@ llvm-cov-flags: --show-branches=count --show-mcdc
|
LL| |//@ llvm-cov-flags: --show-branches=count --show-mcdc
|
||||||
LL| |
|
LL| |
|
||||||
@ -40,11 +40,11 @@
|
|||||||
|
|
|
|
||||||
| C1, C2 Result
|
| C1, C2 Result
|
||||||
| 1 { F, F = F }
|
| 1 { F, F = F }
|
||||||
| 2 { T, - = T }
|
| 2 { F, T = T }
|
||||||
| 3 { F, T = T }
|
| 3 { T, - = T }
|
||||||
|
|
|
|
||||||
| C1-Pair: covered: (1,2)
|
| C1-Pair: covered: (1,3)
|
||||||
| C2-Pair: covered: (1,3)
|
| C2-Pair: covered: (1,2)
|
||||||
| MC/DC Coverage for Decision: 100.00%
|
| MC/DC Coverage for Decision: 100.00%
|
||||||
|
|
|
|
||||||
------------------
|
------------------
|
||||||
@ -92,11 +92,11 @@
|
|||||||
|
|
|
|
||||||
| C1, C2 Result
|
| C1, C2 Result
|
||||||
| 1 { F, F = F }
|
| 1 { F, F = F }
|
||||||
| 2 { T, - = T }
|
| 2 { F, T = T }
|
||||||
| 3 { F, T = T }
|
| 3 { T, - = T }
|
||||||
|
|
|
|
||||||
| C1-Pair: covered: (1,2)
|
| C1-Pair: covered: (1,3)
|
||||||
| C2-Pair: covered: (1,3)
|
| C2-Pair: covered: (1,2)
|
||||||
| MC/DC Coverage for Decision: 100.00%
|
| MC/DC Coverage for Decision: 100.00%
|
||||||
|
|
|
|
||||||
|---> MC/DC Decision Region (LL:24) to (LL:30)
|
|---> MC/DC Decision Region (LL:24) to (LL:30)
|
||||||
@ -195,11 +195,11 @@
|
|||||||
|
|
|
|
||||||
| C1, C2 Result
|
| C1, C2 Result
|
||||||
| 1 { F, F = F }
|
| 1 { F, F = F }
|
||||||
| 2 { T, - = T }
|
| 2 { F, T = T }
|
||||||
| 3 { F, T = T }
|
| 3 { T, - = T }
|
||||||
|
|
|
|
||||||
| C1-Pair: covered: (1,2)
|
| C1-Pair: covered: (1,3)
|
||||||
| C2-Pair: covered: (1,3)
|
| C2-Pair: covered: (1,2)
|
||||||
| MC/DC Coverage for Decision: 100.00%
|
| MC/DC Coverage for Decision: 100.00%
|
||||||
|
|
|
|
||||||
|---> MC/DC Decision Region (LL:28) to (LL:34)
|
|---> MC/DC Decision Region (LL:28) to (LL:34)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#![feature(coverage_attribute)]
|
#![feature(coverage_attribute)]
|
||||||
//@ edition: 2021
|
//@ edition: 2021
|
||||||
//@ ignore-llvm-version: 19 - 99
|
//@ min-llvm-version: 19
|
||||||
//@ compile-flags: -Zcoverage-options=mcdc
|
//@ compile-flags: -Zcoverage-options=mcdc
|
||||||
//@ llvm-cov-flags: --show-branches=count --show-mcdc
|
//@ llvm-cov-flags: --show-branches=count --show-mcdc
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
Function name: non_control_flow::assign_3
|
Function name: non_control_flow::assign_3
|
||||||
Raw bytes (89): 0x[01, 01, 09, 05, 07, 0b, 11, 09, 0d, 01, 05, 01, 05, 22, 11, 01, 05, 22, 11, 01, 05, 0a, 01, 16, 01, 00, 28, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 00, 03, 00, 0d, 00, 18, 30, 05, 22, 01, 00, 02, 00, 0d, 00, 0e, 22, 00, 12, 00, 13, 30, 1e, 11, 02, 03, 00, 00, 12, 00, 13, 1e, 00, 17, 00, 18, 30, 09, 0d, 03, 00, 00, 00, 17, 00, 18, 03, 01, 05, 01, 02]
|
Raw bytes (89): 0x[01, 01, 09, 05, 07, 0b, 11, 09, 0d, 01, 05, 01, 05, 22, 11, 01, 05, 22, 11, 01, 05, 0a, 01, 16, 01, 00, 28, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 04, 03, 00, 0d, 00, 18, 30, 05, 22, 01, 00, 02, 00, 0d, 00, 0e, 22, 00, 12, 00, 13, 30, 1e, 11, 02, 03, 00, 00, 12, 00, 13, 1e, 00, 17, 00, 18, 30, 09, 0d, 03, 00, 00, 00, 17, 00, 18, 03, 01, 05, 01, 02]
|
||||||
Number of files: 1
|
Number of files: 1
|
||||||
- file 0 => global file 1
|
- file 0 => global file 1
|
||||||
Number of expressions: 9
|
Number of expressions: 9
|
||||||
@ -17,7 +17,7 @@ Number of file 0 mappings: 10
|
|||||||
- Code(Expression(0, Add)) at (prev + 1, 9) to (start + 0, 10)
|
- Code(Expression(0, Add)) at (prev + 1, 9) to (start + 0, 10)
|
||||||
= (c1 + ((c2 + c3) + c4))
|
= (c1 + ((c2 + c3) + c4))
|
||||||
- Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14)
|
- Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14)
|
||||||
- MCDCDecision { bitmap_idx: 0, conditions_num: 3 } at (prev + 0, 13) to (start + 0, 24)
|
- MCDCDecision { bitmap_idx: 4, conditions_num: 3 } at (prev + 0, 13) to (start + 0, 24)
|
||||||
- MCDCBranch { true: Counter(1), false: Expression(8, Sub), condition_id: 1, true_next_id: 0, false_next_id: 2 } at (prev + 0, 13) to (start + 0, 14)
|
- MCDCBranch { true: Counter(1), false: Expression(8, Sub), condition_id: 1, true_next_id: 0, false_next_id: 2 } at (prev + 0, 13) to (start + 0, 14)
|
||||||
true = c1
|
true = c1
|
||||||
false = (c0 - c1)
|
false = (c0 - c1)
|
||||||
@ -35,7 +35,7 @@ Number of file 0 mappings: 10
|
|||||||
= (c1 + ((c2 + c3) + c4))
|
= (c1 + ((c2 + c3) + c4))
|
||||||
|
|
||||||
Function name: non_control_flow::assign_3_bis
|
Function name: non_control_flow::assign_3_bis
|
||||||
Raw bytes (85): 0x[01, 01, 07, 07, 11, 09, 0d, 01, 05, 05, 09, 16, 1a, 05, 09, 01, 05, 0a, 01, 1b, 01, 00, 2c, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 00, 03, 00, 0d, 00, 18, 30, 05, 1a, 01, 03, 02, 00, 0d, 00, 0e, 05, 00, 12, 00, 13, 30, 09, 16, 03, 00, 02, 00, 12, 00, 13, 13, 00, 17, 00, 18, 30, 0d, 11, 02, 00, 00, 00, 17, 00, 18, 03, 01, 05, 01, 02]
|
Raw bytes (85): 0x[01, 01, 07, 07, 11, 09, 0d, 01, 05, 05, 09, 16, 1a, 05, 09, 01, 05, 0a, 01, 1b, 01, 00, 2c, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 05, 03, 00, 0d, 00, 18, 30, 05, 1a, 01, 03, 02, 00, 0d, 00, 0e, 05, 00, 12, 00, 13, 30, 09, 16, 03, 00, 02, 00, 12, 00, 13, 13, 00, 17, 00, 18, 30, 0d, 11, 02, 00, 00, 00, 17, 00, 18, 03, 01, 05, 01, 02]
|
||||||
Number of files: 1
|
Number of files: 1
|
||||||
- file 0 => global file 1
|
- file 0 => global file 1
|
||||||
Number of expressions: 7
|
Number of expressions: 7
|
||||||
@ -51,7 +51,7 @@ Number of file 0 mappings: 10
|
|||||||
- Code(Expression(0, Add)) at (prev + 1, 9) to (start + 0, 10)
|
- Code(Expression(0, Add)) at (prev + 1, 9) to (start + 0, 10)
|
||||||
= ((c2 + c3) + c4)
|
= ((c2 + c3) + c4)
|
||||||
- Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14)
|
- Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14)
|
||||||
- MCDCDecision { bitmap_idx: 0, conditions_num: 3 } at (prev + 0, 13) to (start + 0, 24)
|
- MCDCDecision { bitmap_idx: 5, conditions_num: 3 } at (prev + 0, 13) to (start + 0, 24)
|
||||||
- MCDCBranch { true: Counter(1), false: Expression(6, Sub), condition_id: 1, true_next_id: 3, false_next_id: 2 } at (prev + 0, 13) to (start + 0, 14)
|
- MCDCBranch { true: Counter(1), false: Expression(6, Sub), condition_id: 1, true_next_id: 3, false_next_id: 2 } at (prev + 0, 13) to (start + 0, 14)
|
||||||
true = c1
|
true = c1
|
||||||
false = (c0 - c1)
|
false = (c0 - c1)
|
||||||
@ -68,7 +68,7 @@ Number of file 0 mappings: 10
|
|||||||
= ((c2 + c3) + c4)
|
= ((c2 + c3) + c4)
|
||||||
|
|
||||||
Function name: non_control_flow::assign_and
|
Function name: non_control_flow::assign_and
|
||||||
Raw bytes (64): 0x[01, 01, 04, 07, 0e, 09, 0d, 01, 05, 01, 05, 08, 01, 0c, 01, 00, 21, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 00, 02, 00, 0d, 00, 13, 30, 05, 0e, 01, 02, 00, 00, 0d, 00, 0e, 05, 00, 12, 00, 13, 30, 09, 0d, 02, 00, 00, 00, 12, 00, 13, 03, 01, 05, 01, 02]
|
Raw bytes (64): 0x[01, 01, 04, 07, 0e, 09, 0d, 01, 05, 01, 05, 08, 01, 0c, 01, 00, 21, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 03, 02, 00, 0d, 00, 13, 30, 05, 0e, 01, 02, 00, 00, 0d, 00, 0e, 05, 00, 12, 00, 13, 30, 09, 0d, 02, 00, 00, 00, 12, 00, 13, 03, 01, 05, 01, 02]
|
||||||
Number of files: 1
|
Number of files: 1
|
||||||
- file 0 => global file 1
|
- file 0 => global file 1
|
||||||
Number of expressions: 4
|
Number of expressions: 4
|
||||||
@ -81,7 +81,7 @@ Number of file 0 mappings: 8
|
|||||||
- Code(Expression(0, Add)) at (prev + 1, 9) to (start + 0, 10)
|
- Code(Expression(0, Add)) at (prev + 1, 9) to (start + 0, 10)
|
||||||
= ((c2 + c3) + (c0 - c1))
|
= ((c2 + c3) + (c0 - c1))
|
||||||
- Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14)
|
- Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14)
|
||||||
- MCDCDecision { bitmap_idx: 0, conditions_num: 2 } at (prev + 0, 13) to (start + 0, 19)
|
- MCDCDecision { bitmap_idx: 3, conditions_num: 2 } at (prev + 0, 13) to (start + 0, 19)
|
||||||
- MCDCBranch { true: Counter(1), false: Expression(3, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 13) to (start + 0, 14)
|
- MCDCBranch { true: Counter(1), false: Expression(3, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 13) to (start + 0, 14)
|
||||||
true = c1
|
true = c1
|
||||||
false = (c0 - c1)
|
false = (c0 - c1)
|
||||||
@ -93,7 +93,7 @@ Number of file 0 mappings: 8
|
|||||||
= ((c2 + c3) + (c0 - c1))
|
= ((c2 + c3) + (c0 - c1))
|
||||||
|
|
||||||
Function name: non_control_flow::assign_or
|
Function name: non_control_flow::assign_or
|
||||||
Raw bytes (64): 0x[01, 01, 04, 07, 0d, 05, 09, 01, 05, 01, 05, 08, 01, 11, 01, 00, 20, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 00, 02, 00, 0d, 00, 13, 30, 05, 0e, 01, 00, 02, 00, 0d, 00, 0e, 0e, 00, 12, 00, 13, 30, 09, 0d, 02, 00, 00, 00, 12, 00, 13, 03, 01, 05, 01, 02]
|
Raw bytes (64): 0x[01, 01, 04, 07, 0d, 05, 09, 01, 05, 01, 05, 08, 01, 11, 01, 00, 20, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 03, 02, 00, 0d, 00, 13, 30, 05, 0e, 01, 00, 02, 00, 0d, 00, 0e, 0e, 00, 12, 00, 13, 30, 09, 0d, 02, 00, 00, 00, 12, 00, 13, 03, 01, 05, 01, 02]
|
||||||
Number of files: 1
|
Number of files: 1
|
||||||
- file 0 => global file 1
|
- file 0 => global file 1
|
||||||
Number of expressions: 4
|
Number of expressions: 4
|
||||||
@ -106,7 +106,7 @@ Number of file 0 mappings: 8
|
|||||||
- Code(Expression(0, Add)) at (prev + 1, 9) to (start + 0, 10)
|
- Code(Expression(0, Add)) at (prev + 1, 9) to (start + 0, 10)
|
||||||
= ((c1 + c2) + c3)
|
= ((c1 + c2) + c3)
|
||||||
- Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14)
|
- Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14)
|
||||||
- MCDCDecision { bitmap_idx: 0, conditions_num: 2 } at (prev + 0, 13) to (start + 0, 19)
|
- MCDCDecision { bitmap_idx: 3, conditions_num: 2 } at (prev + 0, 13) to (start + 0, 19)
|
||||||
- MCDCBranch { true: Counter(1), false: Expression(3, Sub), condition_id: 1, true_next_id: 0, false_next_id: 2 } at (prev + 0, 13) to (start + 0, 14)
|
- MCDCBranch { true: Counter(1), false: Expression(3, Sub), condition_id: 1, true_next_id: 0, false_next_id: 2 } at (prev + 0, 13) to (start + 0, 14)
|
||||||
true = c1
|
true = c1
|
||||||
false = (c0 - c1)
|
false = (c0 - c1)
|
||||||
@ -127,7 +127,7 @@ Number of file 0 mappings: 1
|
|||||||
- Code(Counter(0)) at (prev + 37, 1) to (start + 2, 2)
|
- Code(Counter(0)) at (prev + 37, 1) to (start + 2, 2)
|
||||||
|
|
||||||
Function name: non_control_flow::func_call
|
Function name: non_control_flow::func_call
|
||||||
Raw bytes (52): 0x[01, 01, 03, 01, 05, 0b, 02, 09, 0d, 06, 01, 29, 01, 01, 0a, 28, 00, 02, 01, 09, 00, 0f, 30, 05, 02, 01, 02, 00, 00, 09, 00, 0a, 05, 00, 0e, 00, 0f, 30, 09, 0d, 02, 00, 00, 00, 0e, 00, 0f, 07, 01, 01, 00, 02]
|
Raw bytes (52): 0x[01, 01, 03, 01, 05, 0b, 02, 09, 0d, 06, 01, 29, 01, 01, 0a, 28, 03, 02, 01, 09, 00, 0f, 30, 05, 02, 01, 02, 00, 00, 09, 00, 0a, 05, 00, 0e, 00, 0f, 30, 09, 0d, 02, 00, 00, 00, 0e, 00, 0f, 07, 01, 01, 00, 02]
|
||||||
Number of files: 1
|
Number of files: 1
|
||||||
- file 0 => global file 1
|
- file 0 => global file 1
|
||||||
Number of expressions: 3
|
Number of expressions: 3
|
||||||
@ -136,7 +136,7 @@ Number of expressions: 3
|
|||||||
- expression 2 operands: lhs = Counter(2), rhs = Counter(3)
|
- expression 2 operands: lhs = Counter(2), rhs = Counter(3)
|
||||||
Number of file 0 mappings: 6
|
Number of file 0 mappings: 6
|
||||||
- Code(Counter(0)) at (prev + 41, 1) to (start + 1, 10)
|
- Code(Counter(0)) at (prev + 41, 1) to (start + 1, 10)
|
||||||
- MCDCDecision { bitmap_idx: 0, conditions_num: 2 } at (prev + 1, 9) to (start + 0, 15)
|
- MCDCDecision { bitmap_idx: 3, conditions_num: 2 } at (prev + 1, 9) to (start + 0, 15)
|
||||||
- MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 9) to (start + 0, 10)
|
- MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 9) to (start + 0, 10)
|
||||||
true = c1
|
true = c1
|
||||||
false = (c0 - c1)
|
false = (c0 - c1)
|
||||||
@ -148,7 +148,7 @@ Number of file 0 mappings: 6
|
|||||||
= ((c2 + c3) + (c0 - c1))
|
= ((c2 + c3) + (c0 - c1))
|
||||||
|
|
||||||
Function name: non_control_flow::right_comb_tree
|
Function name: non_control_flow::right_comb_tree
|
||||||
Raw bytes (139): 0x[01, 01, 13, 07, 1a, 0b, 19, 0f, 15, 13, 11, 09, 0d, 01, 05, 01, 05, 05, 19, 05, 19, 4a, 15, 05, 19, 4a, 15, 05, 19, 46, 11, 4a, 15, 05, 19, 46, 11, 4a, 15, 05, 19, 0e, 01, 20, 01, 00, 41, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 00, 05, 00, 0d, 00, 2a, 30, 05, 1a, 01, 02, 00, 00, 0d, 00, 0e, 05, 00, 13, 00, 14, 30, 4a, 19, 02, 03, 00, 00, 13, 00, 14, 4a, 00, 19, 00, 1a, 30, 46, 15, 03, 04, 00, 00, 19, 00, 1a, 46, 00, 1f, 00, 20, 30, 42, 11, 04, 05, 00, 00, 1f, 00, 20, 42, 00, 24, 00, 27, 30, 09, 0d, 05, 00, 00, 00, 24, 00, 27, 03, 01, 05, 01, 02]
|
Raw bytes (139): 0x[01, 01, 13, 07, 1a, 0b, 19, 0f, 15, 13, 11, 09, 0d, 01, 05, 01, 05, 05, 19, 05, 19, 4a, 15, 05, 19, 4a, 15, 05, 19, 46, 11, 4a, 15, 05, 19, 46, 11, 4a, 15, 05, 19, 0e, 01, 20, 01, 00, 41, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 06, 05, 00, 0d, 00, 2a, 30, 05, 1a, 01, 02, 00, 00, 0d, 00, 0e, 05, 00, 13, 00, 14, 30, 4a, 19, 02, 03, 00, 00, 13, 00, 14, 4a, 00, 19, 00, 1a, 30, 46, 15, 03, 04, 00, 00, 19, 00, 1a, 46, 00, 1f, 00, 20, 30, 42, 11, 04, 05, 00, 00, 1f, 00, 20, 42, 00, 24, 00, 27, 30, 09, 0d, 05, 00, 00, 00, 24, 00, 27, 03, 01, 05, 01, 02]
|
||||||
Number of files: 1
|
Number of files: 1
|
||||||
- file 0 => global file 1
|
- file 0 => global file 1
|
||||||
Number of expressions: 19
|
Number of expressions: 19
|
||||||
@ -176,7 +176,7 @@ Number of file 0 mappings: 14
|
|||||||
- Code(Expression(0, Add)) at (prev + 1, 9) to (start + 0, 10)
|
- Code(Expression(0, Add)) at (prev + 1, 9) to (start + 0, 10)
|
||||||
= (((((c2 + c3) + c4) + c5) + c6) + (c0 - c1))
|
= (((((c2 + c3) + c4) + c5) + c6) + (c0 - c1))
|
||||||
- Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14)
|
- Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14)
|
||||||
- MCDCDecision { bitmap_idx: 0, conditions_num: 5 } at (prev + 0, 13) to (start + 0, 42)
|
- MCDCDecision { bitmap_idx: 6, conditions_num: 5 } at (prev + 0, 13) to (start + 0, 42)
|
||||||
- MCDCBranch { true: Counter(1), false: Expression(6, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 13) to (start + 0, 14)
|
- MCDCBranch { true: Counter(1), false: Expression(6, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 13) to (start + 0, 14)
|
||||||
true = c1
|
true = c1
|
||||||
false = (c0 - c1)
|
false = (c0 - c1)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
LL| |#![feature(coverage_attribute)]
|
LL| |#![feature(coverage_attribute)]
|
||||||
LL| |//@ edition: 2021
|
LL| |//@ edition: 2021
|
||||||
LL| |//@ ignore-llvm-version: 19 - 99
|
LL| |//@ min-llvm-version: 19
|
||||||
LL| |//@ compile-flags: -Zcoverage-options=mcdc
|
LL| |//@ compile-flags: -Zcoverage-options=mcdc
|
||||||
LL| |//@ llvm-cov-flags: --show-branches=count --show-mcdc
|
LL| |//@ llvm-cov-flags: --show-branches=count --show-mcdc
|
||||||
LL| |
|
LL| |
|
||||||
@ -83,11 +83,11 @@
|
|||||||
|
|
|
|
||||||
| C1, C2, C3 Result
|
| C1, C2, C3 Result
|
||||||
| 1 { F, F, - = F }
|
| 1 { F, F, - = F }
|
||||||
| 2 { T, -, - = T }
|
| 2 { F, T, T = T }
|
||||||
| 3 { F, T, T = T }
|
| 3 { T, -, - = T }
|
||||||
|
|
|
|
||||||
| C1-Pair: covered: (1,2)
|
| C1-Pair: covered: (1,3)
|
||||||
| C2-Pair: covered: (1,3)
|
| C2-Pair: covered: (1,2)
|
||||||
| C3-Pair: not covered
|
| C3-Pair: not covered
|
||||||
| MC/DC Coverage for Decision: 66.67%
|
| MC/DC Coverage for Decision: 66.67%
|
||||||
|
|
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#![feature(coverage_attribute)]
|
#![feature(coverage_attribute)]
|
||||||
//@ edition: 2021
|
//@ edition: 2021
|
||||||
//@ ignore-llvm-version: 19 - 99
|
//@ min-llvm-version: 19
|
||||||
//@ compile-flags: -Zcoverage-options=mcdc
|
//@ compile-flags: -Zcoverage-options=mcdc
|
||||||
//@ llvm-cov-flags: --show-branches=count --show-mcdc
|
//@ llvm-cov-flags: --show-branches=count --show-mcdc
|
||||||
|
|
||||||
|
@ -1,8 +0,0 @@
|
|||||||
warning: number of conditions in decision (7) exceeds limit (6), so MC/DC analysis will not count this expression
|
|
||||||
--> $DIR/mcdc-condition-limit.rs:28:8
|
|
||||||
|
|
|
||||||
LL | if a && b && c && d && e && f && g {
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
warning: 1 warning emitted
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
|||||||
//@ edition: 2021
|
//@ edition: 2021
|
||||||
//@ revisions: good bad
|
//@ min-llvm-version: 19
|
||||||
|
//@ revisions: good
|
||||||
//@ check-pass
|
//@ check-pass
|
||||||
//@ compile-flags: -Cinstrument-coverage -Zcoverage-options=mcdc -Zno-profiler-runtime
|
//@ compile-flags: -Cinstrument-coverage -Zcoverage-options=mcdc -Zno-profiler-runtime
|
||||||
|
|
||||||
@ -14,18 +15,9 @@
|
|||||||
|
|
||||||
#[cfg(good)]
|
#[cfg(good)]
|
||||||
fn main() {
|
fn main() {
|
||||||
// 6 conditions is OK, so no diagnostic.
|
// 7 conditions is allowed, so no diagnostic.
|
||||||
let [a, b, c, d, e, f] = <[bool; 6]>::default();
|
|
||||||
if a && b && c && d && e && f {
|
|
||||||
core::hint::black_box("hello");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(bad)]
|
|
||||||
fn main() {
|
|
||||||
// 7 conditions is too many, so issue a diagnostic.
|
|
||||||
let [a, b, c, d, e, f, g] = <[bool; 7]>::default();
|
let [a, b, c, d, e, f, g] = <[bool; 7]>::default();
|
||||||
if a && b && c && d && e && f && g { //[bad]~ WARNING number of conditions in decision
|
if a && b && c && d && e && f && g {
|
||||||
core::hint::black_box("hello");
|
core::hint::black_box("hello");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user