| //! Metadata from source code coverage analysis and instrumentation. |
| |
| use rustc_macros::HashStable; |
| use rustc_span::Symbol; |
| |
| use std::fmt::{self, Debug, Formatter}; |
| |
| rustc_index::newtype_index! { |
| /// ID of a coverage counter. Values ascend from 0. |
| /// |
| /// 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)] |
| #[max = 0xFFFF_FFFF] |
| #[debug_format = "CounterId({})"] |
| pub struct CounterId {} |
| } |
| |
| 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. |
| /// |
| /// 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)] |
| #[max = 0xFFFF_FFFF] |
| #[debug_format = "ExpressionId({})"] |
| pub struct ExpressionId {} |
| } |
| |
| 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) |
| } |
| } |
| |
| rustc_index::newtype_index! { |
| /// MappedExpressionIndex values ascend from zero, and are recalculated indexes based on their |
| /// array position in the LLVM coverage map "Expressions" array, which is assembled during the |
| /// "mapgen" process. They cannot be computed algorithmically, from the other `newtype_index`s. |
| #[derive(HashStable)] |
| #[max = 0xFFFF_FFFF] |
| #[debug_format = "MappedExpressionIndex({})"] |
| pub struct MappedExpressionIndex {} |
| } |
| |
| /// Operand 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. |
| #[derive(Copy, Clone, PartialEq, Eq)] |
| #[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)] |
| pub enum Operand { |
| Zero, |
| Counter(CounterId), |
| Expression(ExpressionId), |
| } |
| |
| impl Debug for Operand { |
| fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { |
| match self { |
| Self::Zero => write!(f, "Zero"), |
| Self::Counter(id) => f.debug_tuple("Counter").field(&id.as_u32()).finish(), |
| Self::Expression(id) => f.debug_tuple("Expression").field(&id.as_u32()).finish(), |
| } |
| } |
| } |
| |
| #[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, |
| } |
| |
| 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"), |
| } |
| } |
| } |
| |
| #[derive(Clone, TyEncodable, TyDecodable, Hash, HashStable, PartialEq, Eq, PartialOrd, Ord)] |
| #[derive(TypeFoldable, TypeVisitable)] |
| pub struct CodeRegion { |
| pub file_name: Symbol, |
| pub start_line: u32, |
| pub start_col: u32, |
| pub end_line: u32, |
| pub end_col: u32, |
| } |
| |
| impl Debug for CodeRegion { |
| fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result { |
| write!( |
| fmt, |
| "{}:{}:{} - {}:{}", |
| self.file_name, self.start_line, self.start_col, self.end_line, self.end_col |
| ) |
| } |
| } |
| |
| #[derive(Copy, Clone, Debug, PartialEq, TyEncodable, TyDecodable, Hash, HashStable)] |
| #[derive(TypeFoldable, TypeVisitable)] |
| pub enum Op { |
| Subtract, |
| Add, |
| } |
| |
| impl Op { |
| pub fn is_add(&self) -> bool { |
| matches!(self, Self::Add) |
| } |
| |
| pub fn is_subtract(&self) -> bool { |
| matches!(self, Self::Subtract) |
| } |
| } |