Skip to content

Commit 60616ad

Browse files
committed
mcdc-coverage: Add possibility for codegen llvm to handle several condition bitmaps
1 parent 3288583 commit 60616ad

File tree

2 files changed

+33
-17
lines changed

2 files changed

+33
-17
lines changed

compiler/rustc_codegen_llvm/src/builder.rs

+20-11
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ use rustc_target::abi::{self, call::FnAbi, Align, Size, WrappingRange};
2727
use rustc_target::spec::{HasTargetSpec, SanitizerSet, Target};
2828
use smallvec::SmallVec;
2929
use std::borrow::Cow;
30+
use std::ffi::CString;
3031
use std::iter;
3132
use std::ops::Deref;
3233
use std::ptr;
@@ -1708,7 +1709,8 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
17081709
fn_name: &'ll Value,
17091710
hash: &'ll Value,
17101711
bitmap_bytes: &'ll Value,
1711-
) -> &'ll Value {
1712+
max_decision_depth: u32,
1713+
) -> Vec<&'ll Value> {
17121714
debug!("mcdc_parameters() with args ({:?}, {:?}, {:?})", fn_name, hash, bitmap_bytes);
17131715

17141716
assert!(llvm_util::get_version() >= (18, 0, 0), "MCDC intrinsics require LLVM 18 or later");
@@ -1721,6 +1723,8 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
17211723
let args = &[fn_name, hash, bitmap_bytes];
17221724
let args = self.check_call("call", llty, llfn, args);
17231725

1726+
let mut cond_bitmaps = vec![];
1727+
17241728
unsafe {
17251729
let _ = llvm::LLVMRustBuildCall(
17261730
self.llbuilder,
@@ -1732,17 +1736,22 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
17321736
0 as c_uint,
17331737
);
17341738
// Create condition bitmap named `mcdc.addr`.
1735-
let mut bx = Builder::with_cx(self.cx);
1736-
bx.position_at_start(llvm::LLVMGetFirstBasicBlock(self.llfn()));
1737-
let cond_bitmap = {
1738-
let alloca =
1739-
llvm::LLVMBuildAlloca(bx.llbuilder, bx.cx.type_i32(), c"mcdc.addr".as_ptr());
1740-
llvm::LLVMSetAlignment(alloca, 4);
1741-
alloca
1742-
};
1743-
bx.store(self.const_i32(0), cond_bitmap, self.tcx().data_layout.i32_align.abi);
1744-
cond_bitmap
1739+
for i in 0..=max_decision_depth {
1740+
let mut bx = Builder::with_cx(self.cx);
1741+
bx.position_at_start(llvm::LLVMGetFirstBasicBlock(self.llfn()));
1742+
1743+
let name = CString::new(format!("mcdc.addr.{i}")).unwrap();
1744+
let cond_bitmap = {
1745+
let alloca =
1746+
llvm::LLVMBuildAlloca(bx.llbuilder, bx.cx.type_i32(), name.as_ptr());
1747+
llvm::LLVMSetAlignment(alloca, 4);
1748+
alloca
1749+
};
1750+
bx.store(self.const_i32(0), cond_bitmap, self.tcx().data_layout.i32_align.abi);
1751+
cond_bitmaps.push(cond_bitmap);
1752+
}
17451753
}
1754+
cond_bitmaps
17461755
}
17471756

17481757
pub(crate) fn mcdc_tvbitmap_update(

compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs

+13-6
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ pub struct CrateCoverageContext<'ll, 'tcx> {
3030
pub(crate) function_coverage_map:
3131
RefCell<FxIndexMap<Instance<'tcx>, FunctionCoverageCollector<'tcx>>>,
3232
pub(crate) pgo_func_name_var_map: RefCell<FxHashMap<Instance<'tcx>, &'ll llvm::Value>>,
33-
pub(crate) mcdc_condition_bitmap_map: RefCell<FxHashMap<Instance<'tcx>, &'ll llvm::Value>>,
33+
pub(crate) mcdc_condition_bitmap_map: RefCell<FxHashMap<Instance<'tcx>, Vec<&'ll llvm::Value>>>,
3434
}
3535

3636
impl<'ll, 'tcx> CrateCoverageContext<'ll, 'tcx> {
@@ -50,8 +50,11 @@ impl<'ll, 'tcx> CrateCoverageContext<'ll, 'tcx> {
5050

5151
/// LLVM use a temp value to record evaluated mcdc test vector of each decision, which is called condition bitmap.
5252
/// This value is named `mcdc.addr` (same as clang) and is a 32-bit integer.
53-
fn try_get_mcdc_condition_bitmap(&self, instance: &Instance<'tcx>) -> Option<&'ll llvm::Value> {
54-
self.mcdc_condition_bitmap_map.borrow().get(instance).copied()
53+
fn try_get_mcdc_condition_bitmap(
54+
&self,
55+
instance: &Instance<'tcx>,
56+
) -> Option<Vec<&'ll llvm::Value>> {
57+
self.mcdc_condition_bitmap_map.borrow().get(instance).cloned()
5558
}
5659
}
5760

@@ -150,9 +153,11 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> {
150153
0,
151154
"ConditionId of evaluated conditions should never be zero"
152155
);
153-
let cond_bitmap = coverage_context
156+
let cond_bitmaps = coverage_context
154157
.try_get_mcdc_condition_bitmap(&instance)
155158
.expect("mcdc cond bitmap should have been allocated for updating");
159+
let cond_bitmap =
160+
cond_bitmaps.get(0).expect("no mcdc cond bitmap with the given depth");
156161
let cond_loc = bx.const_i32(id.as_u32() as i32 - 1);
157162
let bool_value = bx.const_bool(value);
158163
let fn_name = bx.get_pgo_func_name_var(instance);
@@ -161,9 +166,11 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> {
161166
}
162167
CoverageKind::TestVectorBitmapUpdate { bitmap_idx } => {
163168
drop(coverage_map);
164-
let cond_bitmap = coverage_context
169+
let cond_bitmaps = coverage_context
165170
.try_get_mcdc_condition_bitmap(&instance)
166171
.expect("mcdc cond bitmap should have been allocated for merging into the global bitmap");
172+
let cond_bitmap =
173+
cond_bitmaps.get(0).expect("no mcdc cond bitmap with the given depth");
167174
let bitmap_bytes = bx.tcx().coverage_ids_info(instance.def).mcdc_bitmap_bytes;
168175
assert!(bitmap_idx < bitmap_bytes, "bitmap index of the decision out of range");
169176
assert!(
@@ -195,7 +202,7 @@ fn ensure_mcdc_parameters<'ll, 'tcx>(
195202
let fn_name = bx.get_pgo_func_name_var(instance);
196203
let hash = bx.const_u64(function_coverage_info.function_source_hash);
197204
let bitmap_bytes = bx.const_u32(function_coverage_info.mcdc_bitmap_bytes);
198-
let cond_bitmap = bx.mcdc_parameters(fn_name, hash, bitmap_bytes);
205+
let cond_bitmap = bx.mcdc_parameters(fn_name, hash, bitmap_bytes, 1_u32);
199206
bx.coverage_context()
200207
.expect("already checked above")
201208
.mcdc_condition_bitmap_map

0 commit comments

Comments
 (0)