diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-07 05:48:48 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-07 05:48:48 +0000 |
commit | ef24de24a82fe681581cc130f342363c47c0969a (patch) | |
tree | 0d494f7e1a38b95c92426f58fe6eaa877303a86c /compiler/rustc_middle/src/mir/coverage.rs | |
parent | Releasing progress-linux version 1.74.1+dfsg1-1~progress7.99u1. (diff) | |
download | rustc-ef24de24a82fe681581cc130f342363c47c0969a.tar.xz rustc-ef24de24a82fe681581cc130f342363c47c0969a.zip |
Merging upstream version 1.75.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_middle/src/mir/coverage.rs')
-rw-r--r-- | compiler/rustc_middle/src/mir/coverage.rs | 115 |
1 files changed, 72 insertions, 43 deletions
diff --git a/compiler/rustc_middle/src/mir/coverage.rs b/compiler/rustc_middle/src/mir/coverage.rs index 9ef673922..08d377a86 100644 --- a/compiler/rustc_middle/src/mir/coverage.rs +++ b/compiler/rustc_middle/src/mir/coverage.rs @@ -1,5 +1,6 @@ //! Metadata from source code coverage analysis and instrumentation. +use rustc_index::IndexVec; use rustc_macros::HashStable; use rustc_span::Symbol; @@ -8,6 +9,11 @@ use std::fmt::{self, Debug, Formatter}; rustc_index::newtype_index! { /// ID of a coverage counter. Values ascend from 0. /// + /// Before MIR inlining, counter IDs are local to their enclosing function. + /// After MIR inlining, coverage statements may have been inlined into + /// another function, so use the statement's source-scope to find which + /// function/instance its IDs are meaningful for. + /// /// Note that LLVM handles counter IDs as `uint32_t`, so there is no need /// to use a larger representation on the Rust side. #[derive(HashStable)] @@ -18,16 +24,16 @@ rustc_index::newtype_index! { impl CounterId { pub const START: Self = Self::from_u32(0); - - #[inline(always)] - pub fn next_id(self) -> Self { - Self::from_u32(self.as_u32() + 1) - } } rustc_index::newtype_index! { /// ID of a coverage-counter expression. Values ascend from 0. /// + /// Before MIR inlining, expression IDs are local to their enclosing function. + /// After MIR inlining, coverage statements may have been inlined into + /// another function, so use the statement's source-scope to find which + /// function/instance its IDs are meaningful for. + /// /// Note that LLVM handles expression IDs as `uint32_t`, so there is no need /// to use a larger representation on the Rust side. #[derive(HashStable)] @@ -38,26 +44,23 @@ rustc_index::newtype_index! { impl ExpressionId { pub const START: Self = Self::from_u32(0); - - #[inline(always)] - pub fn next_id(self) -> Self { - Self::from_u32(self.as_u32() + 1) - } } -/// Operand of a coverage-counter expression. +/// Enum that can hold a constant zero value, the ID of an physical coverage +/// counter, or the ID of a coverage-counter expression. /// -/// Operands can be a constant zero value, an actual coverage counter, or another -/// expression. Counter/expression operands are referred to by ID. +/// This was originally only used for expression operands (and named `Operand`), +/// but the zero/counter/expression distinction is also useful for representing +/// the value of code/gap mappings, and the true/false arms of branch mappings. #[derive(Copy, Clone, PartialEq, Eq)] #[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)] -pub enum Operand { +pub enum CovTerm { Zero, Counter(CounterId), Expression(ExpressionId), } -impl Debug for Operand { +impl Debug for CovTerm { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { match self { Self::Zero => write!(f, "Zero"), @@ -69,40 +72,31 @@ impl Debug for Operand { #[derive(Clone, PartialEq, TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)] pub enum CoverageKind { - Counter { - function_source_hash: u64, - /// ID of this counter within its enclosing function. - /// Expressions in the same function can refer to it as an operand. - id: CounterId, - }, - Expression { - /// ID of this coverage-counter expression within its enclosing function. - /// Other expressions in the same function can refer to it as an operand. - id: ExpressionId, - lhs: Operand, - op: Op, - rhs: Operand, - }, - Unreachable, + /// Marks the point in MIR control flow represented by a coverage counter. + /// + /// This is eventually lowered to `llvm.instrprof.increment` in LLVM IR. + /// + /// If this statement does not survive MIR optimizations, any mappings that + /// refer to this counter can have those references simplified to zero. + CounterIncrement { id: CounterId }, + + /// Marks the point in MIR control-flow represented by a coverage expression. + /// + /// If this statement does not survive MIR optimizations, any mappings that + /// refer to this expression can have those references simplified to zero. + /// + /// (This is only inserted for expression IDs that are directly used by + /// mappings. Intermediate expressions with no direct mappings are + /// retained/zeroed based on whether they are transitively used.) + ExpressionUsed { id: ExpressionId }, } impl Debug for CoverageKind { fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result { use CoverageKind::*; match self { - Counter { id, .. } => write!(fmt, "Counter({:?})", id.index()), - Expression { id, lhs, op, rhs } => write!( - fmt, - "Expression({:?}) = {:?} {} {:?}", - id.index(), - lhs, - match op { - Op::Add => "+", - Op::Subtract => "-", - }, - rhs, - ), - Unreachable => write!(fmt, "Unreachable"), + CounterIncrement { id } => write!(fmt, "CounterIncrement({:?})", id.index()), + ExpressionUsed { id } => write!(fmt, "ExpressionUsed({:?})", id.index()), } } } @@ -143,3 +137,38 @@ impl Op { matches!(self, Self::Subtract) } } + +#[derive(Clone, Debug)] +#[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)] +pub struct Expression { + pub lhs: CovTerm, + pub op: Op, + pub rhs: CovTerm, +} + +#[derive(Clone, Debug)] +#[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)] +pub struct Mapping { + pub code_region: CodeRegion, + + /// Indicates whether this mapping uses a counter value, expression value, + /// or zero value. + /// + /// FIXME: When we add support for mapping kinds other than `Code` + /// (e.g. branch regions, expansion regions), replace this with a dedicated + /// mapping-kind enum. + pub term: CovTerm, +} + +/// Stores per-function coverage information attached to a `mir::Body`, +/// to be used in conjunction with the individual coverage statements injected +/// into the function's basic blocks. +#[derive(Clone, Debug)] +#[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)] +pub struct FunctionCoverageInfo { + pub function_source_hash: u64, + pub num_counters: usize, + + pub expressions: IndexVec<ExpressionId, Expression>, + pub mappings: Vec<Mapping>, +} |