about summary refs log tree commit diff
path: root/compiler/rustc_codegen_llvm/src/coverageinfo/llvm_cov.rs
diff options
context:
space:
mode:
authorZalathar <Zalathar@users.noreply.github.com>2024-11-01 20:32:20 +1100
committerZalathar <Zalathar@users.noreply.github.com>2024-11-05 15:32:34 +1100
commitb790e4473cad869a4b3cfb46b0a51da6d75f8076 (patch)
tree7d1155f3e8c097bfaa73c272122c94b3c403ac00 /compiler/rustc_codegen_llvm/src/coverageinfo/llvm_cov.rs
parentfbab78289dd8c6e8860034e0048cfb538f217700 (diff)
downloadrust-b790e4473cad869a4b3cfb46b0a51da6d75f8076.tar.gz
rust-b790e4473cad869a4b3cfb46b0a51da6d75f8076.zip
coverage: Extract safe FFI wrapper functions to `llvm_cov`
Diffstat (limited to 'compiler/rustc_codegen_llvm/src/coverageinfo/llvm_cov.rs')
-rw-r--r--compiler/rustc_codegen_llvm/src/coverageinfo/llvm_cov.rs102
1 files changed, 102 insertions, 0 deletions
diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/llvm_cov.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/llvm_cov.rs
new file mode 100644
index 00000000000..56ba45c21ee
--- /dev/null
+++ b/compiler/rustc_codegen_llvm/src/coverageinfo/llvm_cov.rs
@@ -0,0 +1,102 @@
+//! Safe wrappers for coverage-specific FFI functions.
+
+use std::ffi::CString;
+
+use libc::c_uint;
+
+use crate::common::AsCCharPtr;
+use crate::coverageinfo::ffi;
+use crate::llvm;
+
+pub(crate) fn covmap_var_name() -> CString {
+    CString::new(llvm::build_byte_buffer(|s| unsafe {
+        llvm::LLVMRustCoverageWriteMappingVarNameToString(s);
+    }))
+    .expect("covmap variable name should not contain NUL")
+}
+
+pub(crate) fn covmap_section_name(llmod: &llvm::Module) -> CString {
+    CString::new(llvm::build_byte_buffer(|s| unsafe {
+        llvm::LLVMRustCoverageWriteMapSectionNameToString(llmod, s);
+    }))
+    .expect("covmap section name should not contain NUL")
+}
+
+pub(crate) fn covfun_section_name(llmod: &llvm::Module) -> CString {
+    CString::new(llvm::build_byte_buffer(|s| unsafe {
+        llvm::LLVMRustCoverageWriteFuncSectionNameToString(llmod, s);
+    }))
+    .expect("covfun section name should not contain NUL")
+}
+
+pub(crate) fn create_pgo_func_name_var<'ll>(
+    llfn: &'ll llvm::Value,
+    mangled_fn_name: &str,
+) -> &'ll llvm::Value {
+    unsafe {
+        llvm::LLVMRustCoverageCreatePGOFuncNameVar(
+            llfn,
+            mangled_fn_name.as_c_char_ptr(),
+            mangled_fn_name.len(),
+        )
+    }
+}
+
+pub(crate) fn write_filenames_to_buffer<'a>(
+    filenames: impl IntoIterator<Item = &'a str>,
+) -> Vec<u8> {
+    let (pointers, lengths) = filenames
+        .into_iter()
+        .map(|s: &str| (s.as_c_char_ptr(), s.len()))
+        .unzip::<_, _, Vec<_>, Vec<_>>();
+
+    llvm::build_byte_buffer(|buffer| unsafe {
+        llvm::LLVMRustCoverageWriteFilenamesSectionToBuffer(
+            pointers.as_ptr(),
+            pointers.len(),
+            lengths.as_ptr(),
+            lengths.len(),
+            buffer,
+        );
+    })
+}
+
+pub(crate) fn write_function_mappings_to_buffer(
+    virtual_file_mapping: &[u32],
+    expressions: &[ffi::CounterExpression],
+    code_regions: &[ffi::CodeRegion],
+    branch_regions: &[ffi::BranchRegion],
+    mcdc_branch_regions: &[ffi::MCDCBranchRegion],
+    mcdc_decision_regions: &[ffi::MCDCDecisionRegion],
+) -> Vec<u8> {
+    llvm::build_byte_buffer(|buffer| unsafe {
+        llvm::LLVMRustCoverageWriteMappingToBuffer(
+            virtual_file_mapping.as_ptr(),
+            virtual_file_mapping.len() as c_uint,
+            expressions.as_ptr(),
+            expressions.len() as c_uint,
+            code_regions.as_ptr(),
+            code_regions.len() as c_uint,
+            branch_regions.as_ptr(),
+            branch_regions.len() as c_uint,
+            mcdc_branch_regions.as_ptr(),
+            mcdc_branch_regions.len() as c_uint,
+            mcdc_decision_regions.as_ptr(),
+            mcdc_decision_regions.len() as c_uint,
+            buffer,
+        )
+    })
+}
+
+/// Hashes some bytes into a 64-bit hash, via LLVM's `IndexedInstrProf::ComputeHash`,
+/// as required for parts of the LLVM coverage mapping format.
+pub(crate) fn hash_bytes(bytes: &[u8]) -> u64 {
+    unsafe { llvm::LLVMRustCoverageHashByteArray(bytes.as_c_char_ptr(), bytes.len()) }
+}
+
+/// Returns LLVM's `coverage::CovMapVersion::CurrentVersion` (CoverageMapping.h)
+/// as a raw numeric value. For historical reasons, the numeric value is 1 less
+/// than the number in the version's name, so `Version7` is actually `6u32`.
+pub(crate) fn mapping_version() -> u32 {
+    unsafe { llvm::LLVMRustCoverageMappingVersion() }
+}