Rollup merge of #131956 - Zalathar:llvm-counters, r=compiler-errors,Swatinem
coverage: Pass coverage mappings to LLVM as separate structs Instead of trying to cram *N* different kinds of coverage mapping data into a single list for FFI, pass *N* different lists of simpler structs. This avoids the need to fill unused fields with dummy values, and avoids the need to tag structs with their underlying kind. It also lets us call the dedicated LLVM constructors for each different mapping type, instead of having to go through the complex general-purpose constructor. Even though this adds multiple new structs to the FFI surface area, the resulting C++ code is simpler and shorter. --- I've structured this mostly as a single atomic patch, rather than a series of incremental changes, because that avoids the need to make fiddly fixes to code that is about to be deleted anyway.
This commit is contained in:
commit
8f354fc94a
5 changed files with 224 additions and 448 deletions
|
@ -1,11 +1,9 @@
|
||||||
use rustc_middle::mir::coverage::{
|
use rustc_middle::mir::coverage::{CounterId, CovTerm, ExpressionId, SourceRegion};
|
||||||
ConditionInfo, CounterId, CovTerm, DecisionInfo, ExpressionId, MappingKind, SourceRegion,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Must match the layout of `LLVMRustCounterKind`.
|
/// Must match the layout of `LLVMRustCounterKind`.
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub enum CounterKind {
|
pub(crate) enum CounterKind {
|
||||||
Zero = 0,
|
Zero = 0,
|
||||||
CounterValueReference = 1,
|
CounterValueReference = 1,
|
||||||
Expression = 2,
|
Expression = 2,
|
||||||
|
@ -25,9 +23,9 @@ pub enum CounterKind {
|
||||||
/// Must match the layout of `LLVMRustCounter`.
|
/// Must match the layout of `LLVMRustCounter`.
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct Counter {
|
pub(crate) struct Counter {
|
||||||
// Important: The layout (order and types of fields) must match its C++ counterpart.
|
// Important: The layout (order and types of fields) must match its C++ counterpart.
|
||||||
pub kind: CounterKind,
|
pub(crate) kind: CounterKind,
|
||||||
id: u32,
|
id: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,7 +34,7 @@ impl Counter {
|
||||||
pub(crate) const ZERO: Self = Self { kind: CounterKind::Zero, id: 0 };
|
pub(crate) const ZERO: Self = Self { kind: CounterKind::Zero, id: 0 };
|
||||||
|
|
||||||
/// Constructs a new `Counter` of kind `CounterValueReference`.
|
/// Constructs a new `Counter` of kind `CounterValueReference`.
|
||||||
pub fn counter_value_reference(counter_id: CounterId) -> Self {
|
pub(crate) fn counter_value_reference(counter_id: CounterId) -> Self {
|
||||||
Self { kind: CounterKind::CounterValueReference, id: counter_id.as_u32() }
|
Self { kind: CounterKind::CounterValueReference, id: counter_id.as_u32() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,7 +57,7 @@ impl Counter {
|
||||||
/// Must match the layout of `LLVMRustCounterExprKind`.
|
/// Must match the layout of `LLVMRustCounterExprKind`.
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub enum ExprKind {
|
pub(crate) enum ExprKind {
|
||||||
Subtract = 0,
|
Subtract = 0,
|
||||||
Add = 1,
|
Add = 1,
|
||||||
}
|
}
|
||||||
|
@ -69,48 +67,13 @@ pub enum ExprKind {
|
||||||
/// Must match the layout of `LLVMRustCounterExpression`.
|
/// Must match the layout of `LLVMRustCounterExpression`.
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct CounterExpression {
|
pub(crate) struct CounterExpression {
|
||||||
pub kind: ExprKind,
|
pub(crate) kind: ExprKind,
|
||||||
pub lhs: Counter,
|
pub(crate) lhs: Counter,
|
||||||
pub rhs: Counter,
|
pub(crate) rhs: Counter,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Corresponds to enum `llvm::coverage::CounterMappingRegion::RegionKind`.
|
pub(crate) mod mcdc {
|
||||||
///
|
|
||||||
/// 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 {
|
|
||||||
use rustc_middle::mir::coverage::{ConditionId, ConditionInfo, DecisionInfo};
|
use rustc_middle::mir::coverage::{ConditionId, ConditionInfo, DecisionInfo};
|
||||||
|
|
||||||
/// Must match the layout of `LLVMRustMCDCDecisionParameters`.
|
/// Must match the layout of `LLVMRustMCDCDecisionParameters`.
|
||||||
|
@ -121,8 +84,6 @@ mod mcdc {
|
||||||
num_conditions: u16,
|
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;
|
type LLVMConditionId = i16;
|
||||||
|
|
||||||
/// Must match the layout of `LLVMRustMCDCBranchParameters`.
|
/// Must match the layout of `LLVMRustMCDCBranchParameters`.
|
||||||
|
@ -133,38 +94,6 @@ mod mcdc {
|
||||||
condition_ids: [LLVMConditionId; 2],
|
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 {
|
impl From<ConditionInfo> for BranchParameters {
|
||||||
fn from(value: ConditionInfo) -> Self {
|
fn from(value: ConditionInfo) -> Self {
|
||||||
let to_llvm_cond_id = |cond_id: Option<ConditionId>| {
|
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
|
/// A span of source code coordinates to be embedded in coverage metadata.
|
||||||
/// 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).
|
|
||||||
///
|
///
|
||||||
/// Corresponds to struct `llvm::coverage::CounterMappingRegion`.
|
/// Must match the layout of `LLVMRustCoverageSpan`.
|
||||||
///
|
#[derive(Clone, Debug)]
|
||||||
/// Must match the layout of `LLVMRustCounterMappingRegion`.
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct CounterMappingRegion {
|
pub(crate) struct CoverageSpan {
|
||||||
/// The counter type and type-dependent counter data, if any.
|
/// Local index into the function's local-to-global file ID table.
|
||||||
counter: Counter,
|
/// The value at that index is itself an index into the coverage filename
|
||||||
|
/// table in the CGU's `__llvm_covmap` section.
|
||||||
/// 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.
|
|
||||||
file_id: u32,
|
file_id: u32,
|
||||||
|
|
||||||
/// If the `RegionKind` is an `ExpansionRegion`, the `expanded_file_id` can be used to find
|
/// 1-based starting line of the source code span.
|
||||||
/// 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.
|
|
||||||
start_line: u32,
|
start_line: u32,
|
||||||
|
/// 1-based starting column of the source code span.
|
||||||
/// 1-based starting column of the mapping region.
|
|
||||||
start_col: u32,
|
start_col: u32,
|
||||||
|
/// 1-based ending line of the source code span.
|
||||||
/// 1-based ending line of the mapping region.
|
|
||||||
end_line: u32,
|
end_line: u32,
|
||||||
|
/// 1-based ending column of the source code span. High bit must be unset.
|
||||||
/// 1-based ending column of the mapping region. If the high bit is set, the current
|
|
||||||
/// mapping region is a gap area.
|
|
||||||
end_col: u32,
|
end_col: u32,
|
||||||
|
|
||||||
kind: RegionKind,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CounterMappingRegion {
|
impl CoverageSpan {
|
||||||
pub(crate) fn from_mapping(
|
pub(crate) fn from_source_region(file_id: u32, code_region: &SourceRegion) -> Self {
|
||||||
mapping_kind: &MappingKind,
|
let &SourceRegion { file_name: _, start_line, start_col, end_line, end_col } = code_region;
|
||||||
local_file_id: u32,
|
// Internally, LLVM uses the high bit of `end_col` to distinguish between
|
||||||
source_region: &SourceRegion,
|
// code regions and gap regions, so it can't be used by the column number.
|
||||||
) -> Self {
|
assert!(end_col & (1u32 << 31) == 0, "high bit of `end_col` must be unset: {end_col:#X}");
|
||||||
let &SourceRegion { file_name: _, start_line, start_col, end_line, end_col } =
|
Self { file_id, 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,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 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,
|
||||||
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ use rustc_codegen_ssa::traits::{BaseTypeCodegenMethods, ConstCodegenMethods};
|
||||||
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
|
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
|
||||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||||
use rustc_index::IndexVec;
|
use rustc_index::IndexVec;
|
||||||
|
use rustc_middle::mir::coverage::MappingKind;
|
||||||
use rustc_middle::ty::{self, TyCtxt};
|
use rustc_middle::ty::{self, TyCtxt};
|
||||||
use rustc_middle::{bug, mir};
|
use rustc_middle::{bug, mir};
|
||||||
use rustc_span::Symbol;
|
use rustc_span::Symbol;
|
||||||
|
@ -12,7 +13,7 @@ use rustc_span::def_id::DefIdSet;
|
||||||
use tracing::debug;
|
use tracing::debug;
|
||||||
|
|
||||||
use crate::common::CodegenCx;
|
use crate::common::CodegenCx;
|
||||||
use crate::coverageinfo::ffi::CounterMappingRegion;
|
use crate::coverageinfo::ffi;
|
||||||
use crate::coverageinfo::map_data::{FunctionCoverage, FunctionCoverageCollector};
|
use crate::coverageinfo::map_data::{FunctionCoverage, FunctionCoverageCollector};
|
||||||
use crate::{coverageinfo, llvm};
|
use crate::{coverageinfo, llvm};
|
||||||
|
|
||||||
|
@ -237,7 +238,10 @@ fn encode_mappings_for_function(
|
||||||
let expressions = function_coverage.counter_expressions().collect::<Vec<_>>();
|
let expressions = function_coverage.counter_expressions().collect::<Vec<_>>();
|
||||||
|
|
||||||
let mut virtual_file_mapping = VirtualFileMapping::default();
|
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
|
// Group mappings into runs with the same filename, preserving the order
|
||||||
// yielded by `FunctionCoverage`.
|
// yielded by `FunctionCoverage`.
|
||||||
|
@ -257,11 +261,36 @@ fn encode_mappings_for_function(
|
||||||
// form suitable for FFI.
|
// form suitable for FFI.
|
||||||
for (mapping_kind, region) in counter_regions_for_file {
|
for (mapping_kind, region) in counter_regions_for_file {
|
||||||
debug!("Adding counter {mapping_kind:?} to map for {region:?}");
|
debug!("Adding counter {mapping_kind:?} to map for {region:?}");
|
||||||
mapping_regions.push(CounterMappingRegion::from_mapping(
|
let span = ffi::CoverageSpan::from_source_region(local_file_id.as_u32(), region);
|
||||||
&mapping_kind,
|
match mapping_kind {
|
||||||
local_file_id.as_u32(),
|
MappingKind::Code(term) => {
|
||||||
region,
|
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,
|
||||||
|
),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -270,7 +299,10 @@ fn encode_mappings_for_function(
|
||||||
coverageinfo::write_mapping_to_buffer(
|
coverageinfo::write_mapping_to_buffer(
|
||||||
virtual_file_mapping.into_vec(),
|
virtual_file_mapping.into_vec(),
|
||||||
expressions,
|
expressions,
|
||||||
mapping_regions,
|
&code_regions,
|
||||||
|
&branch_regions,
|
||||||
|
&mcdc_branch_regions,
|
||||||
|
&mcdc_decision_regions,
|
||||||
buffer,
|
buffer,
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
|
|
|
@ -18,7 +18,6 @@ use tracing::{debug, instrument};
|
||||||
|
|
||||||
use crate::builder::Builder;
|
use crate::builder::Builder;
|
||||||
use crate::common::CodegenCx;
|
use crate::common::CodegenCx;
|
||||||
use crate::coverageinfo::ffi::{CounterExpression, CounterMappingRegion};
|
|
||||||
use crate::coverageinfo::map_data::FunctionCoverageCollector;
|
use crate::coverageinfo::map_data::FunctionCoverageCollector;
|
||||||
use crate::llvm;
|
use crate::llvm;
|
||||||
|
|
||||||
|
@ -257,8 +256,11 @@ pub(crate) fn write_filenames_section_to_buffer<'a>(
|
||||||
|
|
||||||
pub(crate) fn write_mapping_to_buffer(
|
pub(crate) fn write_mapping_to_buffer(
|
||||||
virtual_file_mapping: Vec<u32>,
|
virtual_file_mapping: Vec<u32>,
|
||||||
expressions: Vec<CounterExpression>,
|
expressions: Vec<ffi::CounterExpression>,
|
||||||
mapping_regions: Vec<CounterMappingRegion>,
|
code_regions: &[ffi::CodeRegion],
|
||||||
|
branch_regions: &[ffi::BranchRegion],
|
||||||
|
mcdc_branch_regions: &[ffi::MCDCBranchRegion],
|
||||||
|
mcdc_decision_regions: &[ffi::MCDCDecisionRegion],
|
||||||
buffer: &RustString,
|
buffer: &RustString,
|
||||||
) {
|
) {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -267,8 +269,14 @@ pub(crate) fn write_mapping_to_buffer(
|
||||||
virtual_file_mapping.len() as c_uint,
|
virtual_file_mapping.len() as c_uint,
|
||||||
expressions.as_ptr(),
|
expressions.as_ptr(),
|
||||||
expressions.len() as c_uint,
|
expressions.len() as c_uint,
|
||||||
mapping_regions.as_ptr(),
|
code_regions.as_ptr(),
|
||||||
mapping_regions.len() as c_uint,
|
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,
|
buffer,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1744,7 +1744,7 @@ unsafe extern "C" {
|
||||||
) -> bool;
|
) -> bool;
|
||||||
|
|
||||||
#[allow(improper_ctypes)]
|
#[allow(improper_ctypes)]
|
||||||
pub fn LLVMRustCoverageWriteFilenamesSectionToBuffer(
|
pub(crate) fn LLVMRustCoverageWriteFilenamesSectionToBuffer(
|
||||||
Filenames: *const *const c_char,
|
Filenames: *const *const c_char,
|
||||||
FilenamesLen: size_t,
|
FilenamesLen: size_t,
|
||||||
Lengths: *const size_t,
|
Lengths: *const size_t,
|
||||||
|
@ -1753,33 +1753,39 @@ unsafe extern "C" {
|
||||||
);
|
);
|
||||||
|
|
||||||
#[allow(improper_ctypes)]
|
#[allow(improper_ctypes)]
|
||||||
pub fn LLVMRustCoverageWriteMappingToBuffer(
|
pub(crate) fn LLVMRustCoverageWriteMappingToBuffer(
|
||||||
VirtualFileMappingIDs: *const c_uint,
|
VirtualFileMappingIDs: *const c_uint,
|
||||||
NumVirtualFileMappingIDs: c_uint,
|
NumVirtualFileMappingIDs: c_uint,
|
||||||
Expressions: *const crate::coverageinfo::ffi::CounterExpression,
|
Expressions: *const crate::coverageinfo::ffi::CounterExpression,
|
||||||
NumExpressions: c_uint,
|
NumExpressions: c_uint,
|
||||||
MappingRegions: *const crate::coverageinfo::ffi::CounterMappingRegion,
|
CodeRegions: *const crate::coverageinfo::ffi::CodeRegion,
|
||||||
NumMappingRegions: c_uint,
|
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,
|
BufferOut: &RustString,
|
||||||
);
|
);
|
||||||
|
|
||||||
pub fn LLVMRustCoverageCreatePGOFuncNameVar(
|
pub(crate) fn LLVMRustCoverageCreatePGOFuncNameVar(
|
||||||
F: &Value,
|
F: &Value,
|
||||||
FuncName: *const c_char,
|
FuncName: *const c_char,
|
||||||
FuncNameLen: size_t,
|
FuncNameLen: size_t,
|
||||||
) -> &Value;
|
) -> &Value;
|
||||||
pub fn LLVMRustCoverageHashByteArray(Bytes: *const c_char, NumBytes: size_t) -> u64;
|
pub(crate) fn LLVMRustCoverageHashByteArray(Bytes: *const c_char, NumBytes: size_t) -> u64;
|
||||||
|
|
||||||
#[allow(improper_ctypes)]
|
#[allow(improper_ctypes)]
|
||||||
pub fn LLVMRustCoverageWriteMapSectionNameToString(M: &Module, Str: &RustString);
|
pub(crate) fn LLVMRustCoverageWriteMapSectionNameToString(M: &Module, Str: &RustString);
|
||||||
|
|
||||||
#[allow(improper_ctypes)]
|
#[allow(improper_ctypes)]
|
||||||
pub fn LLVMRustCoverageWriteFuncSectionNameToString(M: &Module, Str: &RustString);
|
pub(crate) fn LLVMRustCoverageWriteFuncSectionNameToString(M: &Module, Str: &RustString);
|
||||||
|
|
||||||
#[allow(improper_ctypes)]
|
#[allow(improper_ctypes)]
|
||||||
pub fn LLVMRustCoverageWriteMappingVarNameToString(Str: &RustString);
|
pub(crate) fn LLVMRustCoverageWriteMappingVarNameToString(Str: &RustString);
|
||||||
|
|
||||||
pub fn LLVMRustCoverageMappingVersion() -> u32;
|
pub(crate) fn LLVMRustCoverageMappingVersion() -> u32;
|
||||||
pub fn LLVMRustDebugMetadataVersion() -> u32;
|
pub fn LLVMRustDebugMetadataVersion() -> u32;
|
||||||
pub fn LLVMRustVersionMajor() -> u32;
|
pub fn LLVMRustVersionMajor() -> u32;
|
||||||
pub fn LLVMRustVersionMinor() -> u32;
|
pub fn LLVMRustVersionMinor() -> u32;
|
||||||
|
|
|
@ -33,45 +33,6 @@ static coverage::Counter fromRust(LLVMRustCounter Counter) {
|
||||||
report_fatal_error("Bad LLVMRustCounterKind!");
|
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 {
|
struct LLVMRustMCDCDecisionParameters {
|
||||||
uint32_t BitmapIdx;
|
uint32_t BitmapIdx;
|
||||||
uint16_t NumConditions;
|
uint16_t NumConditions;
|
||||||
|
@ -82,47 +43,58 @@ struct LLVMRustMCDCBranchParameters {
|
||||||
int16_t ConditionIDs[2];
|
int16_t ConditionIDs[2];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct LLVMRustMCDCParameters {
|
|
||||||
LLVMRustMCDCParametersTag Tag;
|
|
||||||
LLVMRustMCDCDecisionParameters DecisionParameters;
|
|
||||||
LLVMRustMCDCBranchParameters BranchParameters;
|
|
||||||
};
|
|
||||||
|
|
||||||
#if LLVM_VERSION_GE(19, 0)
|
#if LLVM_VERSION_GE(19, 0)
|
||||||
static coverage::mcdc::Parameters fromRust(LLVMRustMCDCParameters Params) {
|
static coverage::mcdc::BranchParameters
|
||||||
switch (Params.Tag) {
|
fromRust(LLVMRustMCDCBranchParameters Params) {
|
||||||
case LLVMRustMCDCParametersTag::None:
|
return coverage::mcdc::BranchParameters(
|
||||||
return std::monostate();
|
Params.ConditionID, {Params.ConditionIDs[0], Params.ConditionIDs[1]});
|
||||||
case LLVMRustMCDCParametersTag::Decision:
|
}
|
||||||
return coverage::mcdc::DecisionParameters(
|
|
||||||
Params.DecisionParameters.BitmapIdx,
|
static coverage::mcdc::DecisionParameters
|
||||||
Params.DecisionParameters.NumConditions);
|
fromRust(LLVMRustMCDCDecisionParameters Params) {
|
||||||
case LLVMRustMCDCParametersTag::Branch:
|
return coverage::mcdc::DecisionParameters(Params.BitmapIdx,
|
||||||
return coverage::mcdc::BranchParameters(
|
Params.NumConditions);
|
||||||
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!");
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// FFI equivalent of struct `llvm::coverage::CounterMappingRegion`
|
// Must match the layout of
|
||||||
// https://github.com/rust-lang/llvm-project/blob/ea6fa9c2/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L211-L304
|
// `rustc_codegen_llvm::coverageinfo::ffi::CoverageSpan`.
|
||||||
struct LLVMRustCounterMappingRegion {
|
struct LLVMRustCoverageSpan {
|
||||||
LLVMRustCounter Count;
|
|
||||||
LLVMRustCounter FalseCount;
|
|
||||||
LLVMRustMCDCParameters MCDCParameters;
|
|
||||||
uint32_t FileID;
|
uint32_t FileID;
|
||||||
uint32_t ExpandedFileID;
|
|
||||||
uint32_t LineStart;
|
uint32_t LineStart;
|
||||||
uint32_t ColumnStart;
|
uint32_t ColumnStart;
|
||||||
uint32_t LineEnd;
|
uint32_t LineEnd;
|
||||||
uint32_t ColumnEnd;
|
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`
|
// FFI equivalent of enum `llvm::coverage::CounterExpression::ExprKind`
|
||||||
|
@ -174,28 +146,16 @@ extern "C" void LLVMRustCoverageWriteFilenamesSectionToBuffer(
|
||||||
extern "C" void LLVMRustCoverageWriteMappingToBuffer(
|
extern "C" void LLVMRustCoverageWriteMappingToBuffer(
|
||||||
const unsigned *VirtualFileMappingIDs, unsigned NumVirtualFileMappingIDs,
|
const unsigned *VirtualFileMappingIDs, unsigned NumVirtualFileMappingIDs,
|
||||||
const LLVMRustCounterExpression *RustExpressions, unsigned NumExpressions,
|
const LLVMRustCounterExpression *RustExpressions, unsigned NumExpressions,
|
||||||
const LLVMRustCounterMappingRegion *RustMappingRegions,
|
const LLVMRustCoverageCodeRegion *CodeRegions, unsigned NumCodeRegions,
|
||||||
unsigned NumMappingRegions, RustStringRef BufferOut) {
|
const LLVMRustCoverageBranchRegion *BranchRegions,
|
||||||
|
unsigned NumBranchRegions,
|
||||||
|
const LLVMRustCoverageMCDCBranchRegion *MCDCBranchRegions,
|
||||||
|
unsigned NumMCDCBranchRegions,
|
||||||
|
const LLVMRustCoverageMCDCDecisionRegion *MCDCDecisionRegions,
|
||||||
|
unsigned NumMCDCDecisionRegions, RustStringRef BufferOut) {
|
||||||
// Convert from FFI representation to LLVM representation.
|
// 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;
|
std::vector<coverage::CounterExpression> Expressions;
|
||||||
Expressions.reserve(NumExpressions);
|
Expressions.reserve(NumExpressions);
|
||||||
for (const auto &Expression :
|
for (const auto &Expression :
|
||||||
|
@ -205,6 +165,46 @@ extern "C" void LLVMRustCoverageWriteMappingToBuffer(
|
||||||
fromRust(Expression.RHS));
|
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(
|
auto CoverageMappingWriter = coverage::CoverageMappingWriter(
|
||||||
ArrayRef<unsigned>(VirtualFileMappingIDs, NumVirtualFileMappingIDs),
|
ArrayRef<unsigned>(VirtualFileMappingIDs, NumVirtualFileMappingIDs),
|
||||||
Expressions, MappingRegions);
|
Expressions, MappingRegions);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue