1 //! Metadata from source code coverage analysis and instrumentation. 2 3 use rustc_macros::HashStable; 4 use rustc_span::Symbol; 5 6 use std::fmt::{self, Debug, Formatter}; 7 8 rustc_index::newtype_index! { 9 /// An ExpressionOperandId value is assigned directly from either a 10 /// CounterValueReference.as_u32() (which ascend from 1) or an ExpressionOperandId.as_u32() 11 /// (which _*descend*_ from u32::MAX). Id value `0` (zero) represents a virtual counter with a 12 /// constant value of `0`. 13 #[derive(HashStable)] 14 #[max = 0xFFFF_FFFF] 15 #[debug_format = "ExpressionOperandId({})"] 16 pub struct ExpressionOperandId { 17 } 18 } 19 20 impl ExpressionOperandId { 21 /// An expression operand for a "zero counter", as described in the following references: 22 /// 23 /// * <https://github.com/rust-lang/llvm-project/blob/rustc/13.0-2021-09-30/llvm/docs/CoverageMappingFormat.rst#counter> 24 /// * <https://github.com/rust-lang/llvm-project/blob/rustc/13.0-2021-09-30/llvm/docs/CoverageMappingFormat.rst#tag> 25 /// * <https://github.com/rust-lang/llvm-project/blob/rustc/13.0-2021-09-30/llvm/docs/CoverageMappingFormat.rst#counter-expressions> 26 /// 27 /// This operand can be used to count two or more separate code regions with a single counter, 28 /// if they run sequentially with no branches, by injecting the `Counter` in a `BasicBlock` for 29 /// one of the code regions, and inserting `CounterExpression`s ("add ZERO to the counter") in 30 /// the coverage map for the other code regions. 31 pub const ZERO: Self = Self::from_u32(0); 32 } 33 34 rustc_index::newtype_index! { 35 #[derive(HashStable)] 36 #[max = 0xFFFF_FFFF] 37 #[debug_format = "CounterValueReference({})"] 38 pub struct CounterValueReference {} 39 } 40 41 impl CounterValueReference { 42 /// Counters start at 1 to reserve 0 for ExpressionOperandId::ZERO. 43 pub const START: Self = Self::from_u32(1); 44 45 /// Returns explicitly-requested zero-based version of the counter id, used 46 /// during codegen. LLVM expects zero-based indexes. zero_based_index(self) -> u3247 pub fn zero_based_index(self) -> u32 { 48 let one_based_index = self.as_u32(); 49 debug_assert!(one_based_index > 0); 50 one_based_index - 1 51 } 52 } 53 54 rustc_index::newtype_index! { 55 /// InjectedExpressionId.as_u32() converts to ExpressionOperandId.as_u32() 56 /// 57 /// Values descend from u32::MAX. 58 #[derive(HashStable)] 59 #[max = 0xFFFF_FFFF] 60 #[debug_format = "InjectedExpressionId({})"] 61 pub struct InjectedExpressionId {} 62 } 63 64 rustc_index::newtype_index! { 65 /// InjectedExpressionIndex.as_u32() translates to u32::MAX - ExpressionOperandId.as_u32() 66 /// 67 /// Values ascend from 0. 68 #[derive(HashStable)] 69 #[max = 0xFFFF_FFFF] 70 #[debug_format = "InjectedExpressionIndex({})"] 71 pub struct InjectedExpressionIndex {} 72 } 73 74 rustc_index::newtype_index! { 75 /// MappedExpressionIndex values ascend from zero, and are recalculated indexes based on their 76 /// array position in the LLVM coverage map "Expressions" array, which is assembled during the 77 /// "mapgen" process. They cannot be computed algorithmically, from the other `newtype_index`s. 78 #[derive(HashStable)] 79 #[max = 0xFFFF_FFFF] 80 #[debug_format = "MappedExpressionIndex({})"] 81 pub struct MappedExpressionIndex {} 82 } 83 84 impl From<CounterValueReference> for ExpressionOperandId { 85 #[inline] from(v: CounterValueReference) -> ExpressionOperandId86 fn from(v: CounterValueReference) -> ExpressionOperandId { 87 ExpressionOperandId::from(v.as_u32()) 88 } 89 } 90 91 impl From<InjectedExpressionId> for ExpressionOperandId { 92 #[inline] from(v: InjectedExpressionId) -> ExpressionOperandId93 fn from(v: InjectedExpressionId) -> ExpressionOperandId { 94 ExpressionOperandId::from(v.as_u32()) 95 } 96 } 97 98 #[derive(Clone, PartialEq, TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)] 99 pub enum CoverageKind { 100 Counter { 101 function_source_hash: u64, 102 id: CounterValueReference, 103 }, 104 Expression { 105 id: InjectedExpressionId, 106 lhs: ExpressionOperandId, 107 op: Op, 108 rhs: ExpressionOperandId, 109 }, 110 Unreachable, 111 } 112 113 impl CoverageKind { as_operand_id(&self) -> ExpressionOperandId114 pub fn as_operand_id(&self) -> ExpressionOperandId { 115 use CoverageKind::*; 116 match *self { 117 Counter { id, .. } => ExpressionOperandId::from(id), 118 Expression { id, .. } => ExpressionOperandId::from(id), 119 Unreachable => bug!("Unreachable coverage cannot be part of an expression"), 120 } 121 } 122 is_expression(&self) -> bool123 pub fn is_expression(&self) -> bool { 124 matches!(self, Self::Expression { .. }) 125 } 126 } 127 128 impl Debug for CoverageKind { fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result129 fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result { 130 use CoverageKind::*; 131 match self { 132 Counter { id, .. } => write!(fmt, "Counter({:?})", id.index()), 133 Expression { id, lhs, op, rhs } => write!( 134 fmt, 135 "Expression({:?}) = {} {} {}", 136 id.index(), 137 lhs.index(), 138 match op { 139 Op::Add => "+", 140 Op::Subtract => "-", 141 }, 142 rhs.index(), 143 ), 144 Unreachable => write!(fmt, "Unreachable"), 145 } 146 } 147 } 148 149 #[derive(Clone, TyEncodable, TyDecodable, Hash, HashStable, PartialEq, Eq, PartialOrd, Ord)] 150 #[derive(TypeFoldable, TypeVisitable)] 151 pub struct CodeRegion { 152 pub file_name: Symbol, 153 pub start_line: u32, 154 pub start_col: u32, 155 pub end_line: u32, 156 pub end_col: u32, 157 } 158 159 impl Debug for CodeRegion { fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result160 fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result { 161 write!( 162 fmt, 163 "{}:{}:{} - {}:{}", 164 self.file_name, self.start_line, self.start_col, self.end_line, self.end_col 165 ) 166 } 167 } 168 169 #[derive(Copy, Clone, Debug, PartialEq, TyEncodable, TyDecodable, Hash, HashStable)] 170 #[derive(TypeFoldable, TypeVisitable)] 171 pub enum Op { 172 Subtract, 173 Add, 174 } 175 176 impl Op { is_add(&self) -> bool177 pub fn is_add(&self) -> bool { 178 matches!(self, Self::Add) 179 } 180 is_subtract(&self) -> bool181 pub fn is_subtract(&self) -> bool { 182 matches!(self, Self::Subtract) 183 } 184 } 185