]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_middle/src/mir/coverage.rs
New upstream version 1.69.0+dfsg1
[rustc.git] / compiler / rustc_middle / src / mir / coverage.rs
CommitLineData
29967ef6
XL
1//! Metadata from source code coverage analysis and instrumentation.
2
3use rustc_macros::HashStable;
4use rustc_span::Symbol;
5
29967ef6
XL
6use std::fmt::{self, Debug, Formatter};
7
8rustc_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`.
9c376795
FG
13 #[derive(HashStable)]
14 #[max = 0xFFFF_FFFF]
15 #[debug_format = "ExpressionOperandId({})"]
29967ef6 16 pub struct ExpressionOperandId {
29967ef6
XL
17 }
18}
19
20impl ExpressionOperandId {
21 /// An expression operand for a "zero counter", as described in the following references:
22 ///
a2a8927a
XL
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>
29967ef6
XL
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
34rustc_index::newtype_index! {
9c376795
FG
35 #[derive(HashStable)]
36 #[max = 0xFFFF_FFFF]
37 #[debug_format = "CounterValueReference({})"]
38 pub struct CounterValueReference {}
29967ef6
XL
39}
40
41impl CounterValueReference {
cdc7bbd5 42 /// Counters start at 1 to reserve 0 for ExpressionOperandId::ZERO.
29967ef6 43 pub const START: Self = Self::from_u32(1);
cdc7bbd5
XL
44
45 /// Returns explicitly-requested zero-based version of the counter id, used
46 /// during codegen. LLVM expects zero-based indexes.
5e7ed085 47 pub fn zero_based_index(self) -> u32 {
cdc7bbd5
XL
48 let one_based_index = self.as_u32();
49 debug_assert!(one_based_index > 0);
50 one_based_index - 1
51 }
29967ef6
XL
52}
53
54rustc_index::newtype_index! {
55 /// InjectedExpressionId.as_u32() converts to ExpressionOperandId.as_u32()
56 ///
57 /// Values descend from u32::MAX.
9c376795
FG
58 #[derive(HashStable)]
59 #[max = 0xFFFF_FFFF]
60 #[debug_format = "InjectedExpressionId({})"]
61 pub struct InjectedExpressionId {}
29967ef6
XL
62}
63
64rustc_index::newtype_index! {
65 /// InjectedExpressionIndex.as_u32() translates to u32::MAX - ExpressionOperandId.as_u32()
66 ///
67 /// Values ascend from 0.
9c376795
FG
68 #[derive(HashStable)]
69 #[max = 0xFFFF_FFFF]
70 #[debug_format = "InjectedExpressionIndex({})"]
71 pub struct InjectedExpressionIndex {}
29967ef6
XL
72}
73
74rustc_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.
9c376795
FG
78 #[derive(HashStable)]
79 #[max = 0xFFFF_FFFF]
80 #[debug_format = "MappedExpressionIndex({})"]
81 pub struct MappedExpressionIndex {}
29967ef6
XL
82}
83
84impl From<CounterValueReference> for ExpressionOperandId {
85 #[inline]
86 fn from(v: CounterValueReference) -> ExpressionOperandId {
87 ExpressionOperandId::from(v.as_u32())
88 }
89}
90
91impl From<InjectedExpressionId> for ExpressionOperandId {
92 #[inline]
93 fn from(v: InjectedExpressionId) -> ExpressionOperandId {
94 ExpressionOperandId::from(v.as_u32())
95 }
96}
97
064997fb 98#[derive(Clone, PartialEq, TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)]
29967ef6
XL
99pub 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
113impl CoverageKind {
114 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
29967ef6 123 pub fn is_expression(&self) -> bool {
5869c6ff 124 matches!(self, Self::Expression { .. })
29967ef6 125 }
29967ef6
XL
126}
127
128impl Debug for CoverageKind {
129 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(),
9ffffee4
FG
138 match op {
139 Op::Add => "+",
140 Op::Subtract => "-",
141 },
29967ef6
XL
142 rhs.index(),
143 ),
144 Unreachable => write!(fmt, "Unreachable"),
145 }
146 }
147}
148
064997fb
FG
149#[derive(Clone, TyEncodable, TyDecodable, Hash, HashStable, PartialEq, Eq, PartialOrd, Ord)]
150#[derive(TypeFoldable, TypeVisitable)]
29967ef6
XL
151pub 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
159impl Debug for CodeRegion {
160 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
064997fb
FG
169#[derive(Copy, Clone, Debug, PartialEq, TyEncodable, TyDecodable, Hash, HashStable)]
170#[derive(TypeFoldable, TypeVisitable)]
29967ef6
XL
171pub enum Op {
172 Subtract,
173 Add,
174}
cdc7bbd5
XL
175
176impl Op {
177 pub fn is_add(&self) -> bool {
178 matches!(self, Self::Add)
179 }
180
181 pub fn is_subtract(&self) -> bool {
182 matches!(self, Self::Subtract)
183 }
184}