coverage. Lowering MC/DC statements to llvm-ir
This commit is contained in:
@@ -17,7 +17,7 @@ use rustc_data_structures::small_c_str::SmallCStr;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
|
||||
use rustc_middle::ty::layout::{
|
||||
FnAbiError, FnAbiOfHelpers, FnAbiRequest, LayoutError, LayoutOfHelpers, TyAndLayout,
|
||||
FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasTyCtxt, LayoutError, LayoutOfHelpers, TyAndLayout,
|
||||
};
|
||||
use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
|
||||
use rustc_sanitizers::{cfi, kcfi};
|
||||
@@ -1702,4 +1702,128 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
|
||||
};
|
||||
kcfi_bundle
|
||||
}
|
||||
|
||||
pub(crate) fn mcdc_parameters(
|
||||
&mut self,
|
||||
fn_name: &'ll Value,
|
||||
hash: &'ll Value,
|
||||
bitmap_bytes: &'ll Value,
|
||||
) -> &'ll Value {
|
||||
debug!("mcdc_parameters() with args ({:?}, {:?}, {:?})", fn_name, hash, bitmap_bytes);
|
||||
|
||||
assert!(llvm_util::get_version() >= (18, 0, 0), "MCDC intrinsics require LLVM 18 or later");
|
||||
|
||||
let llfn = unsafe { llvm::LLVMRustGetInstrProfMCDCParametersIntrinsic(self.cx().llmod) };
|
||||
let llty = self.cx.type_func(
|
||||
&[self.cx.type_ptr(), self.cx.type_i64(), self.cx.type_i32()],
|
||||
self.cx.type_void(),
|
||||
);
|
||||
let args = &[fn_name, hash, bitmap_bytes];
|
||||
let args = 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,
|
||||
);
|
||||
// Create condition bitmap named `mcdc.addr`.
|
||||
let mut bx = Builder::with_cx(self.cx);
|
||||
bx.position_at_start(llvm::LLVMGetFirstBasicBlock(self.llfn()));
|
||||
let cond_bitmap = {
|
||||
let alloca =
|
||||
llvm::LLVMBuildAlloca(bx.llbuilder, bx.cx.type_i32(), c"mcdc.addr".as_ptr());
|
||||
llvm::LLVMSetAlignment(alloca, 4);
|
||||
alloca
|
||||
};
|
||||
bx.store(self.const_i32(0), cond_bitmap, self.tcx().data_layout.i32_align.abi);
|
||||
cond_bitmap
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn mcdc_tvbitmap_update(
|
||||
&mut self,
|
||||
fn_name: &'ll Value,
|
||||
hash: &'ll Value,
|
||||
bitmap_bytes: &'ll Value,
|
||||
bitmap_index: &'ll Value,
|
||||
mcdc_temp: &'ll Value,
|
||||
) {
|
||||
debug!(
|
||||
"mcdc_tvbitmap_update() with args ({:?}, {:?}, {:?}, {:?}, {:?})",
|
||||
fn_name, hash, bitmap_bytes, bitmap_index, mcdc_temp
|
||||
);
|
||||
assert!(llvm_util::get_version() >= (18, 0, 0), "MCDC intrinsics require LLVM 18 or later");
|
||||
|
||||
let llfn =
|
||||
unsafe { llvm::LLVMRustGetInstrProfMCDCTVBitmapUpdateIntrinsic(self.cx().llmod) };
|
||||
let llty = self.cx.type_func(
|
||||
&[
|
||||
self.cx.type_ptr(),
|
||||
self.cx.type_i64(),
|
||||
self.cx.type_i32(),
|
||||
self.cx.type_i32(),
|
||||
self.cx.type_ptr(),
|
||||
],
|
||||
self.cx.type_void(),
|
||||
);
|
||||
let args = &[fn_name, hash, bitmap_bytes, bitmap_index, mcdc_temp];
|
||||
let args = 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,
|
||||
);
|
||||
}
|
||||
let i32_align = self.tcx().data_layout.i32_align.abi;
|
||||
self.store(self.const_i32(0), mcdc_temp, i32_align);
|
||||
}
|
||||
|
||||
pub(crate) fn mcdc_condbitmap_update(
|
||||
&mut self,
|
||||
fn_name: &'ll Value,
|
||||
hash: &'ll Value,
|
||||
cond_loc: &'ll Value,
|
||||
mcdc_temp: &'ll Value,
|
||||
bool_value: &'ll Value,
|
||||
) {
|
||||
debug!(
|
||||
"mcdc_condbitmap_update() with args ({:?}, {:?}, {:?}, {:?}, {:?})",
|
||||
fn_name, hash, cond_loc, mcdc_temp, bool_value
|
||||
);
|
||||
assert!(llvm_util::get_version() >= (18, 0, 0), "MCDC intrinsics require LLVM 18 or later");
|
||||
let llfn = unsafe { llvm::LLVMRustGetInstrProfMCDCCondBitmapIntrinsic(self.cx().llmod) };
|
||||
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_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,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user