1 //! Metadata from source code coverage analysis and instrumentation.
3 use rustc_macros::HashStable;
4 use rustc_span::Symbol;
7 use std::fmt::{self, Debug, Formatter};
9 rustc_index::newtype_index! {
10 /// An ExpressionOperandId value is assigned directly from either a
11 /// CounterValueReference.as_u32() (which ascend from 1) or an ExpressionOperandId.as_u32()
12 /// (which _*descend*_ from u32::MAX). Id value `0` (zero) represents a virtual counter with a
13 /// constant value of `0`.
14 pub struct ExpressionOperandId {
16 DEBUG_FORMAT = "ExpressionOperandId({})",
21 impl ExpressionOperandId {
22 /// An expression operand for a "zero counter", as described in the following references:
24 /// * <https://github.com/rust-lang/llvm-project/blob/rustc/11.0-2020-10-12/llvm/docs/CoverageMappingFormat.rst#counter>
25 /// * <https://github.com/rust-lang/llvm-project/blob/rustc/11.0-2020-10-12/llvm/docs/CoverageMappingFormat.rst#tag>
26 /// * <https://github.com/rust-lang/llvm-project/blob/rustc/11.0-2020-10-12/llvm/docs/CoverageMappingFormat.rst#counter-expressions>
28 /// This operand can be used to count two or more separate code regions with a single counter,
29 /// if they run sequentially with no branches, by injecting the `Counter` in a `BasicBlock` for
30 /// one of the code regions, and inserting `CounterExpression`s ("add ZERO to the counter") in
31 /// the coverage map for the other code regions.
32 pub const ZERO: Self = Self::from_u32(0);
35 rustc_index::newtype_index! {
36 pub struct CounterValueReference {
38 DEBUG_FORMAT = "CounterValueReference({})",
43 impl CounterValueReference {
44 // Counters start at 1 to reserve 0 for ExpressionOperandId::ZERO.
45 pub const START: Self = Self::from_u32(1);
48 rustc_index::newtype_index! {
49 /// InjectedExpressionId.as_u32() converts to ExpressionOperandId.as_u32()
51 /// Values descend from u32::MAX.
52 pub struct InjectedExpressionId {
54 DEBUG_FORMAT = "InjectedExpressionId({})",
59 rustc_index::newtype_index! {
60 /// InjectedExpressionIndex.as_u32() translates to u32::MAX - ExpressionOperandId.as_u32()
62 /// Values ascend from 0.
63 pub struct InjectedExpressionIndex {
65 DEBUG_FORMAT = "InjectedExpressionIndex({})",
70 rustc_index::newtype_index! {
71 /// MappedExpressionIndex values ascend from zero, and are recalculated indexes based on their
72 /// array position in the LLVM coverage map "Expressions" array, which is assembled during the
73 /// "mapgen" process. They cannot be computed algorithmically, from the other `newtype_index`s.
74 pub struct MappedExpressionIndex {
76 DEBUG_FORMAT = "MappedExpressionIndex({})",
81 impl From<CounterValueReference> for ExpressionOperandId {
83 fn from(v: CounterValueReference) -> ExpressionOperandId {
84 ExpressionOperandId::from(v.as_u32())
88 impl From<InjectedExpressionId> for ExpressionOperandId {
90 fn from(v: InjectedExpressionId) -> ExpressionOperandId {
91 ExpressionOperandId::from(v.as_u32())
95 #[derive(Clone, PartialEq, TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable)]
96 pub enum CoverageKind {
98 function_source_hash: u64,
99 id: CounterValueReference,
102 id: InjectedExpressionId,
103 lhs: ExpressionOperandId,
105 rhs: ExpressionOperandId,
111 pub fn as_operand_id(&self) -> ExpressionOperandId {
114 Counter { id, .. } => ExpressionOperandId::from(id),
115 Expression { id, .. } => ExpressionOperandId::from(id),
116 Unreachable => bug!("Unreachable coverage cannot be part of an expression"),
120 pub fn is_expression(&self) -> bool {
121 matches!(self, Self::Expression { .. })
125 impl Debug for CoverageKind {
126 fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
129 Counter { id, .. } => write!(fmt, "Counter({:?})", id.index()),
130 Expression { id, lhs, op, rhs } => write!(
132 "Expression({:?}) = {} {} {}",
135 if *op == Op::Add { "+" } else { "-" },
138 Unreachable => write!(fmt, "Unreachable"),
155 pub struct CodeRegion {
156 pub file_name: Symbol,
163 impl Debug for CodeRegion {
164 fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
168 self.file_name, self.start_line, self.start_col, self.end_line, self.end_col
173 #[derive(Copy, Clone, Debug, PartialEq, TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable)]