rustc_codegen_llvm/coverageinfo/
llvm_cov.rs

1//! Safe wrappers for coverage-specific FFI functions.
2
3use std::ffi::CString;
4
5use crate::common::AsCCharPtr;
6use crate::coverageinfo::ffi;
7use crate::llvm;
8
9pub(crate) fn covmap_var_name() -> CString {
10    CString::new(llvm::build_byte_buffer(|s| unsafe {
11        llvm::LLVMRustCoverageWriteCovmapVarNameToString(s);
12    }))
13    .expect("covmap variable name should not contain NUL")
14}
15
16pub(crate) fn covmap_section_name(llmod: &llvm::Module) -> CString {
17    CString::new(llvm::build_byte_buffer(|s| unsafe {
18        llvm::LLVMRustCoverageWriteCovmapSectionNameToString(llmod, s);
19    }))
20    .expect("covmap section name should not contain NUL")
21}
22
23pub(crate) fn covfun_section_name(llmod: &llvm::Module) -> CString {
24    CString::new(llvm::build_byte_buffer(|s| unsafe {
25        llvm::LLVMRustCoverageWriteCovfunSectionNameToString(llmod, s);
26    }))
27    .expect("covfun section name should not contain NUL")
28}
29
30pub(crate) fn create_pgo_func_name_var<'ll>(
31    llfn: &'ll llvm::Value,
32    mangled_fn_name: &str,
33) -> &'ll llvm::Value {
34    unsafe {
35        llvm::LLVMRustCoverageCreatePGOFuncNameVar(
36            llfn,
37            mangled_fn_name.as_c_char_ptr(),
38            mangled_fn_name.len(),
39        )
40    }
41}
42
43pub(crate) fn write_filenames_to_buffer(filenames: &[impl AsRef<str>]) -> Vec<u8> {
44    let (pointers, lengths) = filenames
45        .into_iter()
46        .map(AsRef::as_ref)
47        .map(|s: &str| (s.as_c_char_ptr(), s.len()))
48        .unzip::<_, _, Vec<_>, Vec<_>>();
49
50    llvm::build_byte_buffer(|buffer| unsafe {
51        llvm::LLVMRustCoverageWriteFilenamesToBuffer(
52            pointers.as_ptr(),
53            pointers.len(),
54            lengths.as_ptr(),
55            lengths.len(),
56            buffer,
57        );
58    })
59}
60
61pub(crate) fn write_function_mappings_to_buffer(
62    virtual_file_mapping: &[u32],
63    expressions: &[ffi::CounterExpression],
64    regions: &ffi::Regions,
65) -> Vec<u8> {
66    let ffi::Regions { code_regions, branch_regions, mcdc_branch_regions, mcdc_decision_regions } =
67        regions;
68    llvm::build_byte_buffer(|buffer| unsafe {
69        llvm::LLVMRustCoverageWriteFunctionMappingsToBuffer(
70            virtual_file_mapping.as_ptr(),
71            virtual_file_mapping.len(),
72            expressions.as_ptr(),
73            expressions.len(),
74            code_regions.as_ptr(),
75            code_regions.len(),
76            branch_regions.as_ptr(),
77            branch_regions.len(),
78            mcdc_branch_regions.as_ptr(),
79            mcdc_branch_regions.len(),
80            mcdc_decision_regions.as_ptr(),
81            mcdc_decision_regions.len(),
82            buffer,
83        )
84    })
85}
86
87/// Hashes some bytes into a 64-bit hash, via LLVM's `IndexedInstrProf::ComputeHash`,
88/// as required for parts of the LLVM coverage mapping format.
89pub(crate) fn hash_bytes(bytes: &[u8]) -> u64 {
90    unsafe { llvm::LLVMRustCoverageHashBytes(bytes.as_c_char_ptr(), bytes.len()) }
91}
92
93/// Returns LLVM's `coverage::CovMapVersion::CurrentVersion` (CoverageMapping.h)
94/// as a raw numeric value. For historical reasons, the numeric value is 1 less
95/// than the number in the version's name, so `Version7` is actually `6u32`.
96pub(crate) fn mapping_version() -> u32 {
97    unsafe { llvm::LLVMRustCoverageMappingVersion() }
98}