mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 16:24:46 +00:00
Pass coverage mappings to LLVM as separate structs
This commit is contained in:
parent
98c4d96957
commit
d1bf77eb34
@ -1,6 +1,4 @@
|
||||
use rustc_middle::mir::coverage::{
|
||||
ConditionInfo, CounterId, CovTerm, DecisionInfo, ExpressionId, MappingKind, SourceRegion,
|
||||
};
|
||||
use rustc_middle::mir::coverage::{CounterId, CovTerm, ExpressionId, SourceRegion};
|
||||
|
||||
/// Must match the layout of `LLVMRustCounterKind`.
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
@ -75,42 +73,7 @@ pub(crate) struct CounterExpression {
|
||||
pub(crate) rhs: Counter,
|
||||
}
|
||||
|
||||
/// Corresponds to enum `llvm::coverage::CounterMappingRegion::RegionKind`.
|
||||
///
|
||||
/// Must match the layout of `LLVMRustCounterMappingRegionKind`.
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[repr(C)]
|
||||
enum RegionKind {
|
||||
/// A CodeRegion associates some code with a counter
|
||||
CodeRegion = 0,
|
||||
|
||||
/// An ExpansionRegion represents a file expansion region that associates
|
||||
/// a source range with the expansion of a virtual source file, such as
|
||||
/// for a macro instantiation or #include file.
|
||||
ExpansionRegion = 1,
|
||||
|
||||
/// A SkippedRegion represents a source range with code that was skipped
|
||||
/// by a preprocessor or similar means.
|
||||
SkippedRegion = 2,
|
||||
|
||||
/// A GapRegion is like a CodeRegion, but its count is only set as the
|
||||
/// line execution count when its the only region in the line.
|
||||
GapRegion = 3,
|
||||
|
||||
/// A BranchRegion represents leaf-level boolean expressions and is
|
||||
/// associated with two counters, each representing the number of times the
|
||||
/// expression evaluates to true or false.
|
||||
BranchRegion = 4,
|
||||
|
||||
/// A DecisionRegion represents a top-level boolean expression and is
|
||||
/// associated with a variable length bitmap index and condition number.
|
||||
MCDCDecisionRegion = 5,
|
||||
|
||||
/// A Branch Region can be extended to include IDs to facilitate MC/DC.
|
||||
MCDCBranchRegion = 6,
|
||||
}
|
||||
|
||||
mod mcdc {
|
||||
pub(crate) mod mcdc {
|
||||
use rustc_middle::mir::coverage::{ConditionId, ConditionInfo, DecisionInfo};
|
||||
|
||||
/// Must match the layout of `LLVMRustMCDCDecisionParameters`.
|
||||
@ -121,8 +84,6 @@ mod mcdc {
|
||||
num_conditions: u16,
|
||||
}
|
||||
|
||||
// ConditionId in llvm is `unsigned int` at 18 while `int16_t` at
|
||||
// [19](https://github.com/llvm/llvm-project/pull/81257).
|
||||
type LLVMConditionId = i16;
|
||||
|
||||
/// Must match the layout of `LLVMRustMCDCBranchParameters`.
|
||||
@ -133,38 +94,6 @@ mod mcdc {
|
||||
condition_ids: [LLVMConditionId; 2],
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
enum ParameterTag {
|
||||
None = 0,
|
||||
Decision = 1,
|
||||
Branch = 2,
|
||||
}
|
||||
/// Same layout with `LLVMRustMCDCParameters`
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub(crate) struct Parameters {
|
||||
tag: ParameterTag,
|
||||
decision_params: DecisionParameters,
|
||||
branch_params: BranchParameters,
|
||||
}
|
||||
|
||||
impl Parameters {
|
||||
pub(crate) fn none() -> Self {
|
||||
Self {
|
||||
tag: ParameterTag::None,
|
||||
decision_params: Default::default(),
|
||||
branch_params: Default::default(),
|
||||
}
|
||||
}
|
||||
pub(crate) fn decision(decision_params: DecisionParameters) -> Self {
|
||||
Self { tag: ParameterTag::Decision, decision_params, branch_params: Default::default() }
|
||||
}
|
||||
pub(crate) fn branch(branch_params: BranchParameters) -> Self {
|
||||
Self { tag: ParameterTag::Branch, decision_params: Default::default(), branch_params }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ConditionInfo> for BranchParameters {
|
||||
fn from(value: ConditionInfo) -> Self {
|
||||
let to_llvm_cond_id = |cond_id: Option<ConditionId>| {
|
||||
@ -186,267 +115,68 @@ mod mcdc {
|
||||
}
|
||||
}
|
||||
|
||||
/// This struct provides LLVM's representation of a "CoverageMappingRegion", encoded into the
|
||||
/// coverage map, in accordance with the
|
||||
/// [LLVM Code Coverage Mapping Format](https://github.com/rust-lang/llvm-project/blob/rustc/13.0-2021-09-30/llvm/docs/CoverageMappingFormat.rst#llvm-code-coverage-mapping-format).
|
||||
/// The struct composes fields representing the `Counter` type and value(s) (injected counter
|
||||
/// ID, or expression type and operands), the source file (an indirect index into a "filenames
|
||||
/// array", encoded separately), and source location (start and end positions of the represented
|
||||
/// code region).
|
||||
/// A span of source code coordinates to be embedded in coverage metadata.
|
||||
///
|
||||
/// Corresponds to struct `llvm::coverage::CounterMappingRegion`.
|
||||
///
|
||||
/// Must match the layout of `LLVMRustCounterMappingRegion`.
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
/// Must match the layout of `LLVMRustCoverageSpan`.
|
||||
#[derive(Clone, Debug)]
|
||||
#[repr(C)]
|
||||
pub(crate) struct CounterMappingRegion {
|
||||
/// The counter type and type-dependent counter data, if any.
|
||||
counter: Counter,
|
||||
|
||||
/// If the `RegionKind` is a `BranchRegion`, this represents the counter
|
||||
/// for the false branch of the region.
|
||||
false_counter: Counter,
|
||||
|
||||
mcdc_params: mcdc::Parameters,
|
||||
/// An indirect reference to the source filename. In the LLVM Coverage Mapping Format, the
|
||||
/// file_id is an index into a function-specific `virtual_file_mapping` array of indexes
|
||||
/// that, in turn, are used to look up the filename for this region.
|
||||
pub(crate) struct CoverageSpan {
|
||||
/// Local index into the function's local-to-global file ID table.
|
||||
/// The value at that index is itself an index into the coverage filename
|
||||
/// table in the CGU's `__llvm_covmap` section.
|
||||
file_id: u32,
|
||||
|
||||
/// If the `RegionKind` is an `ExpansionRegion`, the `expanded_file_id` can be used to find
|
||||
/// the mapping regions created as a result of macro expansion, by checking if their file id
|
||||
/// matches the expanded file id.
|
||||
expanded_file_id: u32,
|
||||
|
||||
/// 1-based starting line of the mapping region.
|
||||
/// 1-based starting line of the source code span.
|
||||
start_line: u32,
|
||||
|
||||
/// 1-based starting column of the mapping region.
|
||||
/// 1-based starting column of the source code span.
|
||||
start_col: u32,
|
||||
|
||||
/// 1-based ending line of the mapping region.
|
||||
/// 1-based ending line of the source code span.
|
||||
end_line: u32,
|
||||
|
||||
/// 1-based ending column of the mapping region. If the high bit is set, the current
|
||||
/// mapping region is a gap area.
|
||||
/// 1-based ending column of the source code span. High bit must be unset.
|
||||
end_col: u32,
|
||||
|
||||
kind: RegionKind,
|
||||
}
|
||||
|
||||
impl CounterMappingRegion {
|
||||
pub(crate) fn from_mapping(
|
||||
mapping_kind: &MappingKind,
|
||||
local_file_id: u32,
|
||||
source_region: &SourceRegion,
|
||||
) -> Self {
|
||||
let &SourceRegion { file_name: _, start_line, start_col, end_line, end_col } =
|
||||
source_region;
|
||||
match *mapping_kind {
|
||||
MappingKind::Code(term) => Self::code_region(
|
||||
Counter::from_term(term),
|
||||
local_file_id,
|
||||
start_line,
|
||||
start_col,
|
||||
end_line,
|
||||
end_col,
|
||||
),
|
||||
MappingKind::Branch { true_term, false_term } => Self::branch_region(
|
||||
Counter::from_term(true_term),
|
||||
Counter::from_term(false_term),
|
||||
local_file_id,
|
||||
start_line,
|
||||
start_col,
|
||||
end_line,
|
||||
end_col,
|
||||
),
|
||||
MappingKind::MCDCBranch { true_term, false_term, mcdc_params } => {
|
||||
Self::mcdc_branch_region(
|
||||
Counter::from_term(true_term),
|
||||
Counter::from_term(false_term),
|
||||
mcdc_params,
|
||||
local_file_id,
|
||||
start_line,
|
||||
start_col,
|
||||
end_line,
|
||||
end_col,
|
||||
)
|
||||
}
|
||||
MappingKind::MCDCDecision(decision_info) => Self::decision_region(
|
||||
decision_info,
|
||||
local_file_id,
|
||||
start_line,
|
||||
start_col,
|
||||
end_line,
|
||||
end_col,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn code_region(
|
||||
counter: Counter,
|
||||
file_id: u32,
|
||||
start_line: u32,
|
||||
start_col: u32,
|
||||
end_line: u32,
|
||||
end_col: u32,
|
||||
) -> Self {
|
||||
Self {
|
||||
counter,
|
||||
false_counter: Counter::ZERO,
|
||||
mcdc_params: mcdc::Parameters::none(),
|
||||
file_id,
|
||||
expanded_file_id: 0,
|
||||
start_line,
|
||||
start_col,
|
||||
end_line,
|
||||
end_col,
|
||||
kind: RegionKind::CodeRegion,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn branch_region(
|
||||
counter: Counter,
|
||||
false_counter: Counter,
|
||||
file_id: u32,
|
||||
start_line: u32,
|
||||
start_col: u32,
|
||||
end_line: u32,
|
||||
end_col: u32,
|
||||
) -> Self {
|
||||
Self {
|
||||
counter,
|
||||
false_counter,
|
||||
mcdc_params: mcdc::Parameters::none(),
|
||||
file_id,
|
||||
expanded_file_id: 0,
|
||||
start_line,
|
||||
start_col,
|
||||
end_line,
|
||||
end_col,
|
||||
kind: RegionKind::BranchRegion,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn mcdc_branch_region(
|
||||
counter: Counter,
|
||||
false_counter: Counter,
|
||||
condition_info: ConditionInfo,
|
||||
file_id: u32,
|
||||
start_line: u32,
|
||||
start_col: u32,
|
||||
end_line: u32,
|
||||
end_col: u32,
|
||||
) -> Self {
|
||||
Self {
|
||||
counter,
|
||||
false_counter,
|
||||
mcdc_params: mcdc::Parameters::branch(condition_info.into()),
|
||||
file_id,
|
||||
expanded_file_id: 0,
|
||||
start_line,
|
||||
start_col,
|
||||
end_line,
|
||||
end_col,
|
||||
kind: RegionKind::MCDCBranchRegion,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn decision_region(
|
||||
decision_info: DecisionInfo,
|
||||
file_id: u32,
|
||||
start_line: u32,
|
||||
start_col: u32,
|
||||
end_line: u32,
|
||||
end_col: u32,
|
||||
) -> Self {
|
||||
let mcdc_params = mcdc::Parameters::decision(decision_info.into());
|
||||
|
||||
Self {
|
||||
counter: Counter::ZERO,
|
||||
false_counter: Counter::ZERO,
|
||||
mcdc_params,
|
||||
file_id,
|
||||
expanded_file_id: 0,
|
||||
start_line,
|
||||
start_col,
|
||||
end_line,
|
||||
end_col,
|
||||
kind: RegionKind::MCDCDecisionRegion,
|
||||
}
|
||||
}
|
||||
|
||||
// This function might be used in the future; the LLVM API is still evolving, as is coverage
|
||||
// support.
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn expansion_region(
|
||||
file_id: u32,
|
||||
expanded_file_id: u32,
|
||||
start_line: u32,
|
||||
start_col: u32,
|
||||
end_line: u32,
|
||||
end_col: u32,
|
||||
) -> Self {
|
||||
Self {
|
||||
counter: Counter::ZERO,
|
||||
false_counter: Counter::ZERO,
|
||||
mcdc_params: mcdc::Parameters::none(),
|
||||
file_id,
|
||||
expanded_file_id,
|
||||
start_line,
|
||||
start_col,
|
||||
end_line,
|
||||
end_col,
|
||||
kind: RegionKind::ExpansionRegion,
|
||||
}
|
||||
}
|
||||
|
||||
// This function might be used in the future; the LLVM API is still evolving, as is coverage
|
||||
// support.
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn skipped_region(
|
||||
file_id: u32,
|
||||
start_line: u32,
|
||||
start_col: u32,
|
||||
end_line: u32,
|
||||
end_col: u32,
|
||||
) -> Self {
|
||||
Self {
|
||||
counter: Counter::ZERO,
|
||||
false_counter: Counter::ZERO,
|
||||
mcdc_params: mcdc::Parameters::none(),
|
||||
file_id,
|
||||
expanded_file_id: 0,
|
||||
start_line,
|
||||
start_col,
|
||||
end_line,
|
||||
end_col,
|
||||
kind: RegionKind::SkippedRegion,
|
||||
}
|
||||
}
|
||||
|
||||
// This function might be used in the future; the LLVM API is still evolving, as is coverage
|
||||
// support.
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn gap_region(
|
||||
counter: Counter,
|
||||
file_id: u32,
|
||||
start_line: u32,
|
||||
start_col: u32,
|
||||
end_line: u32,
|
||||
end_col: u32,
|
||||
) -> Self {
|
||||
Self {
|
||||
counter,
|
||||
false_counter: Counter::ZERO,
|
||||
mcdc_params: mcdc::Parameters::none(),
|
||||
file_id,
|
||||
expanded_file_id: 0,
|
||||
start_line,
|
||||
start_col,
|
||||
end_line,
|
||||
end_col: (1_u32 << 31) | end_col,
|
||||
kind: RegionKind::GapRegion,
|
||||
}
|
||||
impl CoverageSpan {
|
||||
pub(crate) fn from_source_region(file_id: u32, code_region: &SourceRegion) -> Self {
|
||||
let &SourceRegion { file_name: _, start_line, start_col, end_line, end_col } = code_region;
|
||||
// Internally, LLVM uses the high bit of `end_col` to distinguish between
|
||||
// code regions and gap regions, so it can't be used by the column number.
|
||||
assert!(end_col & (1u32 << 31) == 0, "high bit of `end_col` must be unset: {end_col:#X}");
|
||||
Self { file_id, start_line, start_col, end_line, end_col }
|
||||
}
|
||||
}
|
||||
|
||||
/// Must match the layout of `LLVMRustCoverageCodeRegion`.
|
||||
#[derive(Clone, Debug)]
|
||||
#[repr(C)]
|
||||
pub(crate) struct CodeRegion {
|
||||
pub(crate) span: CoverageSpan,
|
||||
pub(crate) counter: Counter,
|
||||
}
|
||||
|
||||
/// Must match the layout of `LLVMRustCoverageBranchRegion`.
|
||||
#[derive(Clone, Debug)]
|
||||
#[repr(C)]
|
||||
pub(crate) struct BranchRegion {
|
||||
pub(crate) span: CoverageSpan,
|
||||
pub(crate) true_counter: Counter,
|
||||
pub(crate) false_counter: Counter,
|
||||
}
|
||||
|
||||
/// Must match the layout of `LLVMRustCoverageMCDCBranchRegion`.
|
||||
#[derive(Clone, Debug)]
|
||||
#[repr(C)]
|
||||
pub(crate) struct MCDCBranchRegion {
|
||||
pub(crate) span: CoverageSpan,
|
||||
pub(crate) true_counter: Counter,
|
||||
pub(crate) false_counter: Counter,
|
||||
pub(crate) mcdc_branch_params: mcdc::BranchParameters,
|
||||
}
|
||||
|
||||
/// Must match the layout of `LLVMRustCoverageMCDCDecisionRegion`.
|
||||
#[derive(Clone, Debug)]
|
||||
#[repr(C)]
|
||||
pub(crate) struct MCDCDecisionRegion {
|
||||
pub(crate) span: CoverageSpan,
|
||||
pub(crate) mcdc_decision_params: mcdc::DecisionParameters,
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ use rustc_codegen_ssa::traits::{BaseTypeCodegenMethods, ConstCodegenMethods};
|
||||
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_index::IndexVec;
|
||||
use rustc_middle::mir::coverage::MappingKind;
|
||||
use rustc_middle::ty::{self, TyCtxt};
|
||||
use rustc_middle::{bug, mir};
|
||||
use rustc_span::Symbol;
|
||||
@ -10,7 +11,7 @@ use rustc_span::def_id::DefIdSet;
|
||||
use tracing::debug;
|
||||
|
||||
use crate::common::CodegenCx;
|
||||
use crate::coverageinfo::ffi::CounterMappingRegion;
|
||||
use crate::coverageinfo::ffi;
|
||||
use crate::coverageinfo::map_data::{FunctionCoverage, FunctionCoverageCollector};
|
||||
use crate::{coverageinfo, llvm};
|
||||
|
||||
@ -235,7 +236,10 @@ fn encode_mappings_for_function(
|
||||
let expressions = function_coverage.counter_expressions().collect::<Vec<_>>();
|
||||
|
||||
let mut virtual_file_mapping = VirtualFileMapping::default();
|
||||
let mut mapping_regions = Vec::with_capacity(counter_regions.len());
|
||||
let mut code_regions = vec![];
|
||||
let mut branch_regions = vec![];
|
||||
let mut mcdc_branch_regions = vec![];
|
||||
let mut mcdc_decision_regions = vec![];
|
||||
|
||||
// Group mappings into runs with the same filename, preserving the order
|
||||
// yielded by `FunctionCoverage`.
|
||||
@ -255,11 +259,36 @@ fn encode_mappings_for_function(
|
||||
// form suitable for FFI.
|
||||
for (mapping_kind, region) in counter_regions_for_file {
|
||||
debug!("Adding counter {mapping_kind:?} to map for {region:?}");
|
||||
mapping_regions.push(CounterMappingRegion::from_mapping(
|
||||
&mapping_kind,
|
||||
local_file_id.as_u32(),
|
||||
region,
|
||||
));
|
||||
let span = ffi::CoverageSpan::from_source_region(local_file_id.as_u32(), region);
|
||||
match mapping_kind {
|
||||
MappingKind::Code(term) => {
|
||||
code_regions
|
||||
.push(ffi::CodeRegion { span, counter: ffi::Counter::from_term(term) });
|
||||
}
|
||||
MappingKind::Branch { true_term, false_term } => {
|
||||
branch_regions.push(ffi::BranchRegion {
|
||||
span,
|
||||
true_counter: ffi::Counter::from_term(true_term),
|
||||
false_counter: ffi::Counter::from_term(false_term),
|
||||
});
|
||||
}
|
||||
MappingKind::MCDCBranch { true_term, false_term, mcdc_params } => {
|
||||
mcdc_branch_regions.push(ffi::MCDCBranchRegion {
|
||||
span,
|
||||
true_counter: ffi::Counter::from_term(true_term),
|
||||
false_counter: ffi::Counter::from_term(false_term),
|
||||
mcdc_branch_params: ffi::mcdc::BranchParameters::from(mcdc_params),
|
||||
});
|
||||
}
|
||||
MappingKind::MCDCDecision(mcdc_decision_params) => {
|
||||
mcdc_decision_regions.push(ffi::MCDCDecisionRegion {
|
||||
span,
|
||||
mcdc_decision_params: ffi::mcdc::DecisionParameters::from(
|
||||
mcdc_decision_params,
|
||||
),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -268,7 +297,10 @@ fn encode_mappings_for_function(
|
||||
coverageinfo::write_mapping_to_buffer(
|
||||
virtual_file_mapping.into_vec(),
|
||||
expressions,
|
||||
mapping_regions,
|
||||
&code_regions,
|
||||
&branch_regions,
|
||||
&mcdc_branch_regions,
|
||||
&mcdc_decision_regions,
|
||||
buffer,
|
||||
);
|
||||
})
|
||||
|
@ -16,7 +16,6 @@ use tracing::{debug, instrument};
|
||||
|
||||
use crate::builder::Builder;
|
||||
use crate::common::CodegenCx;
|
||||
use crate::coverageinfo::ffi::{CounterExpression, CounterMappingRegion};
|
||||
use crate::coverageinfo::map_data::FunctionCoverageCollector;
|
||||
use crate::llvm;
|
||||
|
||||
@ -255,8 +254,11 @@ pub(crate) fn write_filenames_section_to_buffer<'a>(
|
||||
|
||||
pub(crate) fn write_mapping_to_buffer(
|
||||
virtual_file_mapping: Vec<u32>,
|
||||
expressions: Vec<CounterExpression>,
|
||||
mapping_regions: Vec<CounterMappingRegion>,
|
||||
expressions: Vec<ffi::CounterExpression>,
|
||||
code_regions: &[ffi::CodeRegion],
|
||||
branch_regions: &[ffi::BranchRegion],
|
||||
mcdc_branch_regions: &[ffi::MCDCBranchRegion],
|
||||
mcdc_decision_regions: &[ffi::MCDCDecisionRegion],
|
||||
buffer: &RustString,
|
||||
) {
|
||||
unsafe {
|
||||
@ -265,8 +267,14 @@ pub(crate) fn write_mapping_to_buffer(
|
||||
virtual_file_mapping.len() as c_uint,
|
||||
expressions.as_ptr(),
|
||||
expressions.len() as c_uint,
|
||||
mapping_regions.as_ptr(),
|
||||
mapping_regions.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,
|
||||
);
|
||||
}
|
||||
|
@ -1754,8 +1754,14 @@ unsafe extern "C" {
|
||||
NumVirtualFileMappingIDs: c_uint,
|
||||
Expressions: *const crate::coverageinfo::ffi::CounterExpression,
|
||||
NumExpressions: c_uint,
|
||||
MappingRegions: *const crate::coverageinfo::ffi::CounterMappingRegion,
|
||||
NumMappingRegions: c_uint,
|
||||
CodeRegions: *const crate::coverageinfo::ffi::CodeRegion,
|
||||
NumCodeRegions: c_uint,
|
||||
BranchRegions: *const crate::coverageinfo::ffi::BranchRegion,
|
||||
NumBranchRegions: c_uint,
|
||||
MCDCBranchRegions: *const crate::coverageinfo::ffi::MCDCBranchRegion,
|
||||
NumMCDCBranchRegions: c_uint,
|
||||
MCDCDecisionRegions: *const crate::coverageinfo::ffi::MCDCDecisionRegion,
|
||||
NumMCDCDecisionRegions: c_uint,
|
||||
BufferOut: &RustString,
|
||||
);
|
||||
|
||||
|
@ -33,45 +33,6 @@ static coverage::Counter fromRust(LLVMRustCounter Counter) {
|
||||
report_fatal_error("Bad LLVMRustCounterKind!");
|
||||
}
|
||||
|
||||
// FFI equivalent of enum `llvm::coverage::CounterMappingRegion::RegionKind`
|
||||
// https://github.com/rust-lang/llvm-project/blob/ea6fa9c2/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L213-L234
|
||||
enum class LLVMRustCounterMappingRegionKind {
|
||||
CodeRegion = 0,
|
||||
ExpansionRegion = 1,
|
||||
SkippedRegion = 2,
|
||||
GapRegion = 3,
|
||||
BranchRegion = 4,
|
||||
MCDCDecisionRegion = 5,
|
||||
MCDCBranchRegion = 6
|
||||
};
|
||||
|
||||
static coverage::CounterMappingRegion::RegionKind
|
||||
fromRust(LLVMRustCounterMappingRegionKind Kind) {
|
||||
switch (Kind) {
|
||||
case LLVMRustCounterMappingRegionKind::CodeRegion:
|
||||
return coverage::CounterMappingRegion::CodeRegion;
|
||||
case LLVMRustCounterMappingRegionKind::ExpansionRegion:
|
||||
return coverage::CounterMappingRegion::ExpansionRegion;
|
||||
case LLVMRustCounterMappingRegionKind::SkippedRegion:
|
||||
return coverage::CounterMappingRegion::SkippedRegion;
|
||||
case LLVMRustCounterMappingRegionKind::GapRegion:
|
||||
return coverage::CounterMappingRegion::GapRegion;
|
||||
case LLVMRustCounterMappingRegionKind::BranchRegion:
|
||||
return coverage::CounterMappingRegion::BranchRegion;
|
||||
case LLVMRustCounterMappingRegionKind::MCDCDecisionRegion:
|
||||
return coverage::CounterMappingRegion::MCDCDecisionRegion;
|
||||
case LLVMRustCounterMappingRegionKind::MCDCBranchRegion:
|
||||
return coverage::CounterMappingRegion::MCDCBranchRegion;
|
||||
}
|
||||
report_fatal_error("Bad LLVMRustCounterMappingRegionKind!");
|
||||
}
|
||||
|
||||
enum LLVMRustMCDCParametersTag {
|
||||
None = 0,
|
||||
Decision = 1,
|
||||
Branch = 2,
|
||||
};
|
||||
|
||||
struct LLVMRustMCDCDecisionParameters {
|
||||
uint32_t BitmapIdx;
|
||||
uint16_t NumConditions;
|
||||
@ -82,47 +43,58 @@ struct LLVMRustMCDCBranchParameters {
|
||||
int16_t ConditionIDs[2];
|
||||
};
|
||||
|
||||
struct LLVMRustMCDCParameters {
|
||||
LLVMRustMCDCParametersTag Tag;
|
||||
LLVMRustMCDCDecisionParameters DecisionParameters;
|
||||
LLVMRustMCDCBranchParameters BranchParameters;
|
||||
};
|
||||
|
||||
#if LLVM_VERSION_GE(19, 0)
|
||||
static coverage::mcdc::Parameters fromRust(LLVMRustMCDCParameters Params) {
|
||||
switch (Params.Tag) {
|
||||
case LLVMRustMCDCParametersTag::None:
|
||||
return std::monostate();
|
||||
case LLVMRustMCDCParametersTag::Decision:
|
||||
return coverage::mcdc::DecisionParameters(
|
||||
Params.DecisionParameters.BitmapIdx,
|
||||
Params.DecisionParameters.NumConditions);
|
||||
case LLVMRustMCDCParametersTag::Branch:
|
||||
return coverage::mcdc::BranchParameters(
|
||||
static_cast<coverage::mcdc::ConditionID>(
|
||||
Params.BranchParameters.ConditionID),
|
||||
{static_cast<coverage::mcdc::ConditionID>(
|
||||
Params.BranchParameters.ConditionIDs[0]),
|
||||
static_cast<coverage::mcdc::ConditionID>(
|
||||
Params.BranchParameters.ConditionIDs[1])});
|
||||
}
|
||||
report_fatal_error("Bad LLVMRustMCDCParametersTag!");
|
||||
static coverage::mcdc::BranchParameters
|
||||
fromRust(LLVMRustMCDCBranchParameters Params) {
|
||||
return coverage::mcdc::BranchParameters(
|
||||
Params.ConditionID, {Params.ConditionIDs[0], Params.ConditionIDs[1]});
|
||||
}
|
||||
|
||||
static coverage::mcdc::DecisionParameters
|
||||
fromRust(LLVMRustMCDCDecisionParameters Params) {
|
||||
return coverage::mcdc::DecisionParameters(Params.BitmapIdx,
|
||||
Params.NumConditions);
|
||||
}
|
||||
#endif
|
||||
|
||||
// FFI equivalent of struct `llvm::coverage::CounterMappingRegion`
|
||||
// https://github.com/rust-lang/llvm-project/blob/ea6fa9c2/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L211-L304
|
||||
struct LLVMRustCounterMappingRegion {
|
||||
LLVMRustCounter Count;
|
||||
LLVMRustCounter FalseCount;
|
||||
LLVMRustMCDCParameters MCDCParameters;
|
||||
// Must match the layout of
|
||||
// `rustc_codegen_llvm::coverageinfo::ffi::CoverageSpan`.
|
||||
struct LLVMRustCoverageSpan {
|
||||
uint32_t FileID;
|
||||
uint32_t ExpandedFileID;
|
||||
uint32_t LineStart;
|
||||
uint32_t ColumnStart;
|
||||
uint32_t LineEnd;
|
||||
uint32_t ColumnEnd;
|
||||
LLVMRustCounterMappingRegionKind Kind;
|
||||
};
|
||||
|
||||
// Must match the layout of `rustc_codegen_llvm::coverageinfo::ffi::CodeRegion`.
|
||||
struct LLVMRustCoverageCodeRegion {
|
||||
LLVMRustCoverageSpan Span;
|
||||
LLVMRustCounter Count;
|
||||
};
|
||||
|
||||
// Must match the layout of
|
||||
// `rustc_codegen_llvm::coverageinfo::ffi::BranchRegion`.
|
||||
struct LLVMRustCoverageBranchRegion {
|
||||
LLVMRustCoverageSpan Span;
|
||||
LLVMRustCounter TrueCount;
|
||||
LLVMRustCounter FalseCount;
|
||||
};
|
||||
|
||||
// Must match the layout of
|
||||
// `rustc_codegen_llvm::coverageinfo::ffi::MCDCBranchRegion`.
|
||||
struct LLVMRustCoverageMCDCBranchRegion {
|
||||
LLVMRustCoverageSpan Span;
|
||||
LLVMRustCounter TrueCount;
|
||||
LLVMRustCounter FalseCount;
|
||||
LLVMRustMCDCBranchParameters MCDCBranchParams;
|
||||
};
|
||||
|
||||
// Must match the layout of
|
||||
// `rustc_codegen_llvm::coverageinfo::ffi::MCDCDecisionRegion`.
|
||||
struct LLVMRustCoverageMCDCDecisionRegion {
|
||||
LLVMRustCoverageSpan Span;
|
||||
LLVMRustMCDCDecisionParameters MCDCDecisionParams;
|
||||
};
|
||||
|
||||
// FFI equivalent of enum `llvm::coverage::CounterExpression::ExprKind`
|
||||
@ -174,28 +146,16 @@ extern "C" void LLVMRustCoverageWriteFilenamesSectionToBuffer(
|
||||
extern "C" void LLVMRustCoverageWriteMappingToBuffer(
|
||||
const unsigned *VirtualFileMappingIDs, unsigned NumVirtualFileMappingIDs,
|
||||
const LLVMRustCounterExpression *RustExpressions, unsigned NumExpressions,
|
||||
const LLVMRustCounterMappingRegion *RustMappingRegions,
|
||||
unsigned NumMappingRegions, RustStringRef BufferOut) {
|
||||
const LLVMRustCoverageCodeRegion *CodeRegions, unsigned NumCodeRegions,
|
||||
const LLVMRustCoverageBranchRegion *BranchRegions,
|
||||
unsigned NumBranchRegions,
|
||||
const LLVMRustCoverageMCDCBranchRegion *MCDCBranchRegions,
|
||||
unsigned NumMCDCBranchRegions,
|
||||
const LLVMRustCoverageMCDCDecisionRegion *MCDCDecisionRegions,
|
||||
unsigned NumMCDCDecisionRegions, RustStringRef BufferOut) {
|
||||
// Convert from FFI representation to LLVM representation.
|
||||
SmallVector<coverage::CounterMappingRegion, 0> MappingRegions;
|
||||
MappingRegions.reserve(NumMappingRegions);
|
||||
for (const auto &Region : ArrayRef<LLVMRustCounterMappingRegion>(
|
||||
RustMappingRegions, NumMappingRegions)) {
|
||||
MappingRegions.emplace_back(
|
||||
fromRust(Region.Count), fromRust(Region.FalseCount),
|
||||
#if LLVM_VERSION_LT(19, 0)
|
||||
coverage::CounterMappingRegion::MCDCParameters{},
|
||||
#endif
|
||||
Region.FileID, Region.ExpandedFileID, // File IDs, then region info.
|
||||
Region.LineStart, Region.ColumnStart, Region.LineEnd, Region.ColumnEnd,
|
||||
fromRust(Region.Kind)
|
||||
#if LLVM_VERSION_GE(19, 0)
|
||||
,
|
||||
fromRust(Region.MCDCParameters)
|
||||
#endif
|
||||
);
|
||||
}
|
||||
|
||||
// Expressions:
|
||||
std::vector<coverage::CounterExpression> Expressions;
|
||||
Expressions.reserve(NumExpressions);
|
||||
for (const auto &Expression :
|
||||
@ -205,6 +165,46 @@ extern "C" void LLVMRustCoverageWriteMappingToBuffer(
|
||||
fromRust(Expression.RHS));
|
||||
}
|
||||
|
||||
std::vector<coverage::CounterMappingRegion> MappingRegions;
|
||||
MappingRegions.reserve(NumCodeRegions + NumBranchRegions +
|
||||
NumMCDCBranchRegions + NumMCDCDecisionRegions);
|
||||
|
||||
// Code regions:
|
||||
for (const auto &Region : ArrayRef(CodeRegions, NumCodeRegions)) {
|
||||
MappingRegions.push_back(coverage::CounterMappingRegion::makeRegion(
|
||||
fromRust(Region.Count), Region.Span.FileID, Region.Span.LineStart,
|
||||
Region.Span.ColumnStart, Region.Span.LineEnd, Region.Span.ColumnEnd));
|
||||
}
|
||||
|
||||
// Branch regions:
|
||||
for (const auto &Region : ArrayRef(BranchRegions, NumBranchRegions)) {
|
||||
MappingRegions.push_back(coverage::CounterMappingRegion::makeBranchRegion(
|
||||
fromRust(Region.TrueCount), fromRust(Region.FalseCount),
|
||||
Region.Span.FileID, Region.Span.LineStart, Region.Span.ColumnStart,
|
||||
Region.Span.LineEnd, Region.Span.ColumnEnd));
|
||||
}
|
||||
|
||||
#if LLVM_VERSION_GE(19, 0)
|
||||
// MC/DC branch regions:
|
||||
for (const auto &Region : ArrayRef(MCDCBranchRegions, NumMCDCBranchRegions)) {
|
||||
MappingRegions.push_back(coverage::CounterMappingRegion::makeBranchRegion(
|
||||
fromRust(Region.TrueCount), fromRust(Region.FalseCount),
|
||||
Region.Span.FileID, Region.Span.LineStart, Region.Span.ColumnStart,
|
||||
Region.Span.LineEnd, Region.Span.ColumnEnd,
|
||||
fromRust(Region.MCDCBranchParams)));
|
||||
}
|
||||
|
||||
// MC/DC decision regions:
|
||||
for (const auto &Region :
|
||||
ArrayRef(MCDCDecisionRegions, NumMCDCDecisionRegions)) {
|
||||
MappingRegions.push_back(coverage::CounterMappingRegion::makeDecisionRegion(
|
||||
fromRust(Region.MCDCDecisionParams), Region.Span.FileID,
|
||||
Region.Span.LineStart, Region.Span.ColumnStart, Region.Span.LineEnd,
|
||||
Region.Span.ColumnEnd));
|
||||
}
|
||||
#endif
|
||||
|
||||
// Write the converted expressions and mappings to a byte buffer.
|
||||
auto CoverageMappingWriter = coverage::CoverageMappingWriter(
|
||||
ArrayRef<unsigned>(VirtualFileMappingIDs, NumVirtualFileMappingIDs),
|
||||
Expressions, MappingRegions);
|
||||
|
Loading…
Reference in New Issue
Block a user