Skip to content

Commit 4e83879

Browse files
committed
coverage: Set up MC/DC bitmaps without additional unsafe code
Because this now always takes place at the start of the function, we can just use the normal `alloca` method and then initialize each bitmap immediately. This patch also moves bitmap setup out of the `mcdc_parameters` method, because there is no longer any particular reason for it to be there.
1 parent 94fe931 commit 4e83879

File tree

4 files changed

+36
-29
lines changed

4 files changed

+36
-29
lines changed

compiler/rustc_abi/src/lib.rs

+3
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ use rustc_macros::{Decodable_Generic, Encodable_Generic};
2121
use std::iter::Step;
2222

2323
mod layout;
24+
#[cfg(test)]
25+
mod tests;
2426

2527
pub use layout::LayoutCalculator;
2628

@@ -698,6 +700,7 @@ impl fmt::Display for AlignFromBytesError {
698700

699701
impl Align {
700702
pub const ONE: Align = Align { pow2: 0 };
703+
pub const FOUR: Align = Align { pow2: 2 };
701704
pub const EIGHT: Align = Align { pow2: 3 };
702705
// LLVM has a maximal supported alignment of 2^29, we inherit that.
703706
pub const MAX: Align = Align { pow2: 29 };

compiler/rustc_abi/src/tests.rs

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
use super::*;
2+
3+
#[test]
4+
fn align_constants() {
5+
assert_eq!(Align::ONE, Align::from_bytes(1).unwrap());
6+
assert_eq!(Align::FOUR, Align::from_bytes(4).unwrap());
7+
assert_eq!(Align::EIGHT, Align::from_bytes(8).unwrap());
8+
}

compiler/rustc_codegen_llvm/src/builder.rs

+12-24
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use rustc_data_structures::small_c_str::SmallCStr;
1717
use rustc_hir::def_id::DefId;
1818
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
1919
use rustc_middle::ty::layout::{
20-
FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasTyCtxt, LayoutError, LayoutOfHelpers, TyAndLayout,
20+
FnAbiError, FnAbiOfHelpers, FnAbiRequest, LayoutError, LayoutOfHelpers, TyAndLayout,
2121
};
2222
use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
2323
use rustc_sanitizers::{cfi, kcfi};
@@ -27,7 +27,6 @@ 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;
3130
use std::iter;
3231
use std::ops::Deref;
3332
use std::ptr;
@@ -1705,13 +1704,21 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
17051704
kcfi_bundle
17061705
}
17071706

1707+
/// Emits a call to `llvm.instrprof.mcdc.parameters`.
1708+
///
1709+
/// This doesn't produce any code directly, but is used as input by
1710+
/// the LLVM pass that handles coverage instrumentation.
1711+
///
1712+
/// (See clang's [`CodeGenPGO::emitMCDCParameters`] for comparison.)
1713+
///
1714+
/// [`CodeGenPGO::emitMCDCParameters`]:
1715+
/// https://github.com/rust-lang/llvm-project/blob/5399a24/clang/lib/CodeGen/CodeGenPGO.cpp#L1124
17081716
pub(crate) fn mcdc_parameters(
17091717
&mut self,
17101718
fn_name: &'ll Value,
17111719
hash: &'ll Value,
17121720
bitmap_bytes: &'ll Value,
1713-
max_decision_depth: u32,
1714-
) -> Vec<&'ll Value> {
1721+
) {
17151722
debug!("mcdc_parameters() with args ({:?}, {:?}, {:?})", fn_name, hash, bitmap_bytes);
17161723

17171724
assert!(llvm_util::get_version() >= (18, 0, 0), "MCDC intrinsics require LLVM 18 or later");
@@ -1724,8 +1731,6 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
17241731
let args = &[fn_name, hash, bitmap_bytes];
17251732
let args = self.check_call("call", llty, llfn, args);
17261733

1727-
let mut cond_bitmaps = vec![];
1728-
17291734
unsafe {
17301735
let _ = llvm::LLVMRustBuildCall(
17311736
self.llbuilder,
@@ -1736,23 +1741,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
17361741
[].as_ptr(),
17371742
0 as c_uint,
17381743
);
1739-
// Create condition bitmap named `mcdc.addr`.
1740-
for i in 0..=max_decision_depth {
1741-
let mut bx = Builder::with_cx(self.cx);
1742-
bx.position_at_start(llvm::LLVMGetFirstBasicBlock(self.llfn()));
1743-
1744-
let name = CString::new(format!("mcdc.addr.{i}")).unwrap();
1745-
let cond_bitmap = {
1746-
let alloca =
1747-
llvm::LLVMBuildAlloca(bx.llbuilder, bx.cx.type_i32(), name.as_ptr());
1748-
llvm::LLVMSetAlignment(alloca, 4);
1749-
alloca
1750-
};
1751-
bx.store(self.const_i32(0), cond_bitmap, self.tcx().data_layout.i32_align.abi);
1752-
cond_bitmaps.push(cond_bitmap);
1753-
}
17541744
}
1755-
cond_bitmaps
17561745
}
17571746

17581747
pub(crate) fn mcdc_tvbitmap_update(
@@ -1794,8 +1783,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
17941783
0 as c_uint,
17951784
);
17961785
}
1797-
let i32_align = self.tcx().data_layout.i32_align.abi;
1798-
self.store(self.const_i32(0), mcdc_temp, i32_align);
1786+
self.store(self.const_i32(0), mcdc_temp, Align::FOUR);
17991787
}
18001788

18011789
pub(crate) fn mcdc_condbitmap_update(

compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs

+13-5
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use rustc_middle::bug;
1616
use rustc_middle::mir::coverage::CoverageKind;
1717
use rustc_middle::ty::layout::HasTyCtxt;
1818
use rustc_middle::ty::Instance;
19-
use rustc_target::abi::Align;
19+
use rustc_target::abi::{Align, Size};
2020

2121
use std::cell::RefCell;
2222

@@ -106,15 +106,23 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> {
106106
let fn_name = self.get_pgo_func_name_var(instance);
107107
let hash = self.const_u64(function_coverage_info.function_source_hash);
108108
let bitmap_bytes = self.const_u32(function_coverage_info.mcdc_bitmap_bytes);
109-
let max_decision_depth = function_coverage_info.mcdc_max_decision_depth;
110-
let cond_bitmap =
111-
self.mcdc_parameters(fn_name, hash, bitmap_bytes, max_decision_depth as u32);
109+
self.mcdc_parameters(fn_name, hash, bitmap_bytes);
110+
111+
// Create locals for condition bitmaps named `mcdc.addr.{i}`.
112+
let mut cond_bitmaps = vec![];
113+
for i in 0..=function_coverage_info.mcdc_max_decision_depth {
114+
let align = Align::FOUR;
115+
let cond_bitmap = self.alloca(Size::from_bytes(4), align);
116+
llvm::set_value_name(cond_bitmap, format!("mcdc.addr.{i}").as_bytes());
117+
self.store(self.const_i32(0), cond_bitmap, align);
118+
cond_bitmaps.push(cond_bitmap);
119+
}
112120

113121
self.coverage_context()
114122
.expect("always present when coverage is enabled")
115123
.mcdc_condition_bitmap_map
116124
.borrow_mut()
117-
.insert(instance, cond_bitmap);
125+
.insert(instance, cond_bitmaps);
118126
}
119127

120128
#[instrument(level = "debug", skip(self))]

0 commit comments

Comments
 (0)