Skip to content

Commit bce5815

Browse files
committed
Generally working expressions
Still not fully optimized to remove unneeded expressions, or expressions that complicate the MIR a bit without really improving coverage or efficiency. Getting some coverage results that don't seem right: * In three tests, the last line of the function (last brace) is counted twice. * In simple_match, the { let z; match is counted zero times (and used to be uncovered) but how would a developer ever get non-zero coverage for this code?
1 parent 6d78047 commit bce5815

File tree

93 files changed

+2814
-632
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

93 files changed

+2814
-632
lines changed

compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use rustc_codegen_ssa::traits::{
1212
use rustc_data_structures::fx::FxHashMap;
1313
use rustc_llvm::RustString;
1414
use rustc_middle::mir::coverage::{
15-
CodeRegion, CounterValueReference, ExpressionOperandId, InjectedExpressionIndex, Op,
15+
CodeRegion, CounterValueReference, ExpressionOperandId, InjectedExpressionId, Op,
1616
};
1717
use rustc_middle::ty::Instance;
1818

@@ -80,7 +80,7 @@ impl CoverageInfoBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
8080
fn add_coverage_counter_expression(
8181
&mut self,
8282
instance: Instance<'tcx>,
83-
id: InjectedExpressionIndex,
83+
id: InjectedExpressionId,
8484
lhs: ExpressionOperandId,
8585
op: Op,
8686
rhs: ExpressionOperandId,

compiler/rustc_codegen_ssa/src/coverageinfo/ffi.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use rustc_middle::mir::coverage::{CounterValueReference, MappedExpressionIndex};
33
/// Aligns with [llvm::coverage::Counter::CounterKind](https://github.com/rust-lang/llvm-project/blob/rustc/10.0-2020-05-05/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L91)
44
#[derive(Copy, Clone, Debug)]
55
#[repr(C)]
6-
enum CounterKind {
6+
pub enum CounterKind {
77
Zero = 0,
88
CounterValueReference = 1,
99
Expression = 2,
@@ -23,8 +23,8 @@ enum CounterKind {
2323
#[repr(C)]
2424
pub struct Counter {
2525
// Important: The layout (order and types of fields) must match its C++ counterpart.
26-
kind: CounterKind,
27-
id: u32,
26+
pub kind: CounterKind,
27+
pub id: u32,
2828
}
2929

3030
impl Counter {
@@ -55,9 +55,9 @@ pub enum ExprKind {
5555
#[derive(Copy, Clone, Debug)]
5656
#[repr(C)]
5757
pub struct CounterExpression {
58-
kind: ExprKind,
59-
lhs: Counter,
60-
rhs: Counter,
58+
pub kind: ExprKind,
59+
pub lhs: Counter,
60+
pub rhs: Counter,
6161
}
6262

6363
impl CounterExpression {

compiler/rustc_codegen_ssa/src/coverageinfo/map.rs

Lines changed: 18 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ pub use super::ffi::*;
22

33
use rustc_index::vec::IndexVec;
44
use rustc_middle::mir::coverage::{
5-
CodeRegion, CounterValueReference, ExpressionOperandId, InjectedExpressionIndex,
6-
MappedExpressionIndex, Op,
5+
CodeRegion, CounterValueReference, ExpressionOperandId, InjectedExpressionId,
6+
InjectedExpressionIndex, MappedExpressionIndex, Op,
77
};
88
use rustc_middle::ty::Instance;
99
use rustc_middle::ty::TyCtxt;
@@ -78,12 +78,13 @@ impl FunctionCoverage {
7878
/// counters and expressions have been added.
7979
pub fn add_counter_expression(
8080
&mut self,
81-
expression_id: InjectedExpressionIndex,
81+
expression_id: InjectedExpressionId,
8282
lhs: ExpressionOperandId,
8383
op: Op,
8484
rhs: ExpressionOperandId,
8585
region: Option<CodeRegion>,
8686
) {
87+
debug!("add_counter_expression({:?}, lhs={:?}, op={:?}, rhs={:?} at {:?}", expression_id, lhs, op, rhs, region);
8788
let expression_index = self.expression_index(u32::from(expression_id));
8889
self.expressions[expression_index]
8990
.replace(Expression { lhs, op, rhs, region })
@@ -134,63 +135,36 @@ impl FunctionCoverage {
134135
let mut counter_expressions = Vec::with_capacity(self.expressions.len());
135136
let mut expression_regions = Vec::with_capacity(self.expressions.len());
136137
let mut new_indexes =
137-
IndexVec::from_elem_n(MappedExpressionIndex::from(u32::MAX), self.expressions.len());
138-
// Note, the initial value shouldn't matter since every index in use in `self.expressions`
139-
// will be set, and after that, `new_indexes` will only be accessed using those same
140-
// indexes.
141-
138+
IndexVec::from_elem_n(None, self.expressions.len());
142139
// Note that an `Expression`s at any given index can include other expressions as
143140
// operands, but expression operands can only come from the subset of expressions having
144141
// `expression_index`s lower than the referencing `Expression`. Therefore, it is
145142
// reasonable to look up the new index of an expression operand while the `new_indexes`
146143
// vector is only complete up to the current `ExpressionIndex`.
147144
let id_to_counter =
148-
|new_indexes: &IndexVec<InjectedExpressionIndex, MappedExpressionIndex>,
145+
|new_indexes: &IndexVec<InjectedExpressionIndex, Option<MappedExpressionIndex>>,
149146
id: ExpressionOperandId| {
150147
if id == ExpressionOperandId::ZERO {
151148
Some(Counter::zero())
152149
} else if id.index() < self.counters.len() {
153150
let index = CounterValueReference::from(id.index());
154151
self.counters
155152
.get(index)
156-
.unwrap() // pre-validated
157-
// TODO(richkadel): is it really pre-validated?
158-
// What if I add some counters that never get added to the map, and they are
159-
// larger than the number of counters in the MIR (as seems to happen with expressions below?)
153+
.expect("counter id is out of range")
160154
.as_ref()
161155
.map(|_| Counter::counter_value_reference(index))
162156
} else {
163157
let index = self.expression_index(u32::from(id));
164-
// TODO(richkadel): remove this debug
165-
debug!(
166-
"id_to_counter expression id={:?}, self.expressions.get(index={:?}) = {:?}",
167-
id,
168-
index,
169-
self.expressions.get(index)
170-
);
171158
self.expressions
172159
.get(index)
173-
// TODO(richkadel): Now some tests generate segfault, and other tests hit this out of range error
174-
// Some expressions reference blocks that ended up not needing counters.
175-
// Can we assume the expression is no longer relevant? If not, then instrument_counters
176-
// transform pass will need to figure this out earlier (MAYBE IT SHOULD ANYWAY?)
177-
// and if the counter is needed for an expression that can no longer be resolved,
178-
// create a new make_counter() right there?
179-
//
180-
// MUST FIX!
181-
//
182-
// It looks like the segfault is at:
183-
//
184-
// /usr/local/google/home/richkadel/rust/src/llvm-project/llvm/lib/ProfileData/Coverage/CoverageMappingWriter.cpp:93
185-
// AdjustedExpressionIDs[ID] = 1;
186-
//
187-
// I think we have expressions with operand IDs that don't exist as either counters or expressions, and that's breaking
188-
// the LLVM code.
189-
// TODO(richkadel): replace expect() with unwrap_or()?
190160
.expect("expression id is out of range")
191-
// .unwrap_or(&None)
192161
.as_ref()
193-
.map(|_| Counter::expression(new_indexes[index]))
162+
// If an expression was optimized out, assume it would have produced a count
163+
// of zero. This ensures that expressions dependent on optimized-out
164+
// expressions are still valid.
165+
.map_or(Some(Counter::zero()), |_| {
166+
new_indexes[index].map(|new_index| Counter::expression(new_index))
167+
})
194168
}
195169
};
196170

@@ -201,6 +175,8 @@ impl FunctionCoverage {
201175
entry.as_ref().map(|expression| (original_index, expression))
202176
})
203177
{
178+
// TODO(richkadel): remove this debug:
179+
debug!("Attempting to add {:?} = {:?}", original_index, expression);
204180
let optional_region = &expression.region;
205181
let Expression { lhs, op, rhs, .. } = *expression;
206182

@@ -209,6 +185,8 @@ impl FunctionCoverage {
209185
id_to_counter(&new_indexes, rhs).map(|rhs_counter| (lhs_counter, rhs_counter))
210186
})
211187
{
188+
debug_assert!((lhs_counter.id as usize) < usize::max(self.counters.len(), self.expressions.len()));
189+
debug_assert!((rhs_counter.id as usize) < usize::max(self.counters.len(), self.expressions.len()));
212190
// Both operands exist. `Expression` operands exist in `self.expressions` and have
213191
// been assigned a `new_index`.
214192
let mapped_expression_index =
@@ -226,7 +204,7 @@ impl FunctionCoverage {
226204
mapped_expression_index, expression, optional_region
227205
);
228206
counter_expressions.push(expression);
229-
new_indexes[original_index] = mapped_expression_index;
207+
new_indexes[original_index] = Some(mapped_expression_index);
230208
if let Some(region) = optional_region {
231209
expression_regions.push((Counter::expression(mapped_expression_index), region));
232210
}

compiler/rustc_codegen_ssa/src/traits/coverageinfo.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ pub trait CoverageInfoBuilderMethods<'tcx>: BackendTypes {
2020
fn add_coverage_counter_expression(
2121
&mut self,
2222
instance: Instance<'tcx>,
23-
id: InjectedExpressionIndex,
23+
id: InjectedExpressionId,
2424
lhs: ExpressionOperandId,
2525
op: Op,
2626
rhs: ExpressionOperandId,

compiler/rustc_middle/src/mir/coverage.rs

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ use std::cmp::Ord;
77
use std::fmt::{self, Debug, Formatter};
88

99
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`.
1014
pub struct ExpressionOperandId {
1115
derive [HashStable]
1216
DEBUG_FORMAT = "ExpressionOperandId({})",
@@ -42,6 +46,20 @@ impl CounterValueReference {
4246
}
4347

4448
rustc_index::newtype_index! {
49+
/// InjectedExpressionId.as_u32() converts to ExpressionOperandId.as_u32()
50+
///
51+
/// Values descend from u32::MAX.
52+
pub struct InjectedExpressionId {
53+
derive [HashStable]
54+
DEBUG_FORMAT = "InjectedExpressionId({})",
55+
MAX = 0xFFFF_FFFF,
56+
}
57+
}
58+
59+
rustc_index::newtype_index! {
60+
/// InjectedExpressionIndex.as_u32() translates to u32::MAX - ExpressionOperandId.as_u32()
61+
///
62+
/// Values ascend from 0.
4563
pub struct InjectedExpressionIndex {
4664
derive [HashStable]
4765
DEBUG_FORMAT = "InjectedExpressionIndex({})",
@@ -50,6 +68,9 @@ rustc_index::newtype_index! {
5068
}
5169

5270
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.
5374
pub struct MappedExpressionIndex {
5475
derive [HashStable]
5576
DEBUG_FORMAT = "MappedExpressionIndex({})",
@@ -71,16 +92,16 @@ impl From<&mut CounterValueReference> for ExpressionOperandId {
7192
}
7293
}
7394

74-
impl From<InjectedExpressionIndex> for ExpressionOperandId {
95+
impl From<InjectedExpressionId> for ExpressionOperandId {
7596
#[inline]
76-
fn from(v: InjectedExpressionIndex) -> ExpressionOperandId {
97+
fn from(v: InjectedExpressionId) -> ExpressionOperandId {
7798
ExpressionOperandId::from(v.as_u32())
7899
}
79100
}
80101

81-
impl From<&mut InjectedExpressionIndex> for ExpressionOperandId {
102+
impl From<&mut InjectedExpressionId> for ExpressionOperandId {
82103
#[inline]
83-
fn from(v: &mut InjectedExpressionIndex) -> ExpressionOperandId {
104+
fn from(v: &mut InjectedExpressionId) -> ExpressionOperandId {
84105
ExpressionOperandId::from(v.as_u32())
85106
}
86107
}
@@ -92,7 +113,7 @@ pub enum CoverageKind {
92113
id: CounterValueReference,
93114
},
94115
Expression {
95-
id: InjectedExpressionIndex,
116+
id: InjectedExpressionId,
96117
lhs: ExpressionOperandId,
97118
op: Op,
98119
rhs: ExpressionOperandId,

compiler/rustc_middle/src/ty/structural_impls.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,7 @@ CloneTypeFoldableAndLiftImpls! {
299299
::rustc_target::spec::abi::Abi,
300300
crate::mir::coverage::ExpressionOperandId,
301301
crate::mir::coverage::CounterValueReference,
302+
crate::mir::coverage::InjectedExpressionId,
302303
crate::mir::coverage::InjectedExpressionIndex,
303304
crate::mir::coverage::MappedExpressionIndex,
304305
crate::mir::Local,

0 commit comments

Comments
 (0)