1 use rustc_middle::mir::coverage::{CounterValueReference, MappedExpressionIndex}; 2 3 /// Must match the layout of `LLVMRustCounterKind`. 4 #[derive(Copy, Clone, Debug)] 5 #[repr(C)] 6 pub enum CounterKind { 7 Zero = 0, 8 CounterValueReference = 1, 9 Expression = 2, 10 } 11 12 /// A reference to an instance of an abstract "counter" that will yield a value in a coverage 13 /// report. Note that `id` has different interpretations, depending on the `kind`: 14 /// * For `CounterKind::Zero`, `id` is assumed to be `0` 15 /// * For `CounterKind::CounterValueReference`, `id` matches the `counter_id` of the injected 16 /// instrumentation counter (the `index` argument to the LLVM intrinsic 17 /// `instrprof.increment()`) 18 /// * For `CounterKind::Expression`, `id` is the index into the coverage map's array of 19 /// counter expressions. 20 /// 21 /// Corresponds to struct `llvm::coverage::Counter`. 22 /// 23 /// Must match the layout of `LLVMRustCounter`. 24 #[derive(Copy, Clone, Debug)] 25 #[repr(C)] 26 pub struct Counter { 27 // Important: The layout (order and types of fields) must match its C++ counterpart. 28 pub kind: CounterKind, 29 id: u32, 30 } 31 32 impl Counter { 33 /// Constructs a new `Counter` of kind `Zero`. For this `CounterKind`, the 34 /// `id` is not used. zero() -> Self35 pub fn zero() -> Self { 36 Self { kind: CounterKind::Zero, id: 0 } 37 } 38 39 /// Constructs a new `Counter` of kind `CounterValueReference`, and converts 40 /// the given 1-based counter_id to the required 0-based equivalent for 41 /// the `Counter` encoding. counter_value_reference(counter_id: CounterValueReference) -> Self42 pub fn counter_value_reference(counter_id: CounterValueReference) -> Self { 43 Self { kind: CounterKind::CounterValueReference, id: counter_id.zero_based_index() } 44 } 45 46 /// Constructs a new `Counter` of kind `Expression`. expression(mapped_expression_index: MappedExpressionIndex) -> Self47 pub fn expression(mapped_expression_index: MappedExpressionIndex) -> Self { 48 Self { kind: CounterKind::Expression, id: mapped_expression_index.into() } 49 } 50 51 /// Returns true if the `Counter` kind is `Zero`. is_zero(&self) -> bool52 pub fn is_zero(&self) -> bool { 53 matches!(self.kind, CounterKind::Zero) 54 } 55 56 /// An explicitly-named function to get the ID value, making it more obvious 57 /// that the stored value is now 0-based. zero_based_id(&self) -> u3258 pub fn zero_based_id(&self) -> u32 { 59 debug_assert!(!self.is_zero(), "`id` is undefined for CounterKind::Zero"); 60 self.id 61 } 62 } 63 64 /// Corresponds to enum `llvm::coverage::CounterExpression::ExprKind`. 65 /// 66 /// Must match the layout of `LLVMRustCounterExprKind`. 67 #[derive(Copy, Clone, Debug)] 68 #[repr(C)] 69 pub enum ExprKind { 70 Subtract = 0, 71 Add = 1, 72 } 73 74 /// Corresponds to struct `llvm::coverage::CounterExpression`. 75 /// 76 /// Must match the layout of `LLVMRustCounterExpression`. 77 #[derive(Copy, Clone, Debug)] 78 #[repr(C)] 79 pub struct CounterExpression { 80 pub kind: ExprKind, 81 pub lhs: Counter, 82 pub rhs: Counter, 83 } 84 85 impl CounterExpression { new(lhs: Counter, kind: ExprKind, rhs: Counter) -> Self86 pub fn new(lhs: Counter, kind: ExprKind, rhs: Counter) -> Self { 87 Self { kind, lhs, rhs } 88 } 89 } 90