Skip to content

Commit 8532e74

Browse files
committed
Auto merge of rust-lang#78267 - richkadel:llvm-coverage-counters-2.0.3r1, r=tmandry
Working expression optimization, and some improvements to branch-level source coverage This replaces PR rust-lang#78040 after reorganizing the original commits (by request) into a more logical sequence of major changes. Most of the work is in the MIR `transform/coverage/` directory (originally, `transform/instrument_coverage.rs`). Note this PR includes some significant additional debugging capabilities, to help myself and any future developer working on coverage improvements or issues. In particular, there's a new Graphviz (.dot file) output for the coverage graph (the `BasicCoverageBlock` control flow graph) that provides ways to get some very good insight into the relationships between the MIR, the coverage graph BCBs, coverage spans, and counters. (There are also some cool debugging options, available via environment variable, to alter how some data in the graph appears.) And the code for this Graphviz view is actually generic... it can be used by any implementation of the Rust `Graph` traits. Finally (for now), I also now output information from `llvm-cov` that shows the actual counters and spans it found in the coverage map, and their counts (from the `--debug` flag). I found this to be enormously helpful in debugging some coverage issues, so I kept it in the test results as well for additional context. `@tmandry` `@wesleywiser` r? `@tmandry` Here's an example of the new coverage graph: * Within each `BasicCoverageBlock` (BCB), you can see each `CoverageSpan` and its contributing statements (MIR `Statement`s and/or `Terminator`s) * Each `CoverageSpan` has a `Counter` or and `Expression`, and `Expression`s show their Add/Subtract operation with nested operations. (This can be changed to show the Counter and Expression IDs instead, or in addition to, the BCB.) * The terminators of all MIR `BasicBlock`s in the BCB, including one final `Terminator` * If an "edge counter" is required (because we need to count an edge between blocks, in some cases) the edge's Counter or Expression is shown next to its label. (Not shown in the example below.) (FYI, Edge Counters are converted into a new MIR `BasicBlock` with `Goto`) <img width="1116" alt="Screen Shot 2020-10-17 at 12 23 29 AM" src="https://user-images.githubusercontent.com/3827298/96331095-616cb480-100f-11eb-8212-60f2d433e2d8.png"> r? `@tmandry` FYI: `@wesleywiser`
2 parents f92b931 + 68014e6 commit 8532e74

File tree

234 files changed

+14070
-2119
lines changed

Some content is hidden

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

234 files changed

+14070
-2119
lines changed

compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ impl CoverageMapGenerator {
129129
let (filenames_index, _) = self.filenames.insert_full(c_filename);
130130
virtual_file_mapping.push(filenames_index as u32);
131131
}
132-
debug!("Adding counter {:?} to map for {:?}", counter, region,);
132+
debug!("Adding counter {:?} to map for {:?}", counter, region);
133133
mapping_regions.push(CounterMappingRegion::code_region(
134134
counter,
135135
current_file_id,

compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs

+41-22
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

@@ -27,16 +27,16 @@ const COVMAP_VAR_ALIGN_BYTES: usize = 8;
2727

2828
/// A context object for maintaining all state needed by the coverageinfo module.
2929
pub struct CrateCoverageContext<'tcx> {
30-
// Coverage region data for each instrumented function identified by DefId.
31-
pub(crate) function_coverage_map: RefCell<FxHashMap<Instance<'tcx>, FunctionCoverage>>,
30+
// Coverage data for each instrumented function identified by DefId.
31+
pub(crate) function_coverage_map: RefCell<FxHashMap<Instance<'tcx>, FunctionCoverage<'tcx>>>,
3232
}
3333

3434
impl<'tcx> CrateCoverageContext<'tcx> {
3535
pub fn new() -> Self {
3636
Self { function_coverage_map: Default::default() }
3737
}
3838

39-
pub fn take_function_coverage_map(&self) -> FxHashMap<Instance<'tcx>, FunctionCoverage> {
39+
pub fn take_function_coverage_map(&self) -> FxHashMap<Instance<'tcx>, FunctionCoverage<'tcx>> {
4040
self.function_coverage_map.replace(FxHashMap::default())
4141
}
4242
}
@@ -58,47 +58,66 @@ impl CoverageInfoBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
5858
unsafe { llvm::LLVMRustCoverageCreatePGOFuncNameVar(llfn, mangled_fn_name.as_ptr()) }
5959
}
6060

61-
fn add_counter_region(
61+
fn set_function_source_hash(
6262
&mut self,
6363
instance: Instance<'tcx>,
6464
function_source_hash: u64,
65+
) -> bool {
66+
if let Some(coverage_context) = self.coverage_context() {
67+
debug!(
68+
"ensuring function source hash is set for instance={:?}; function_source_hash={}",
69+
instance, function_source_hash,
70+
);
71+
let mut coverage_map = coverage_context.function_coverage_map.borrow_mut();
72+
coverage_map
73+
.entry(instance)
74+
.or_insert_with(|| FunctionCoverage::new(self.tcx, instance))
75+
.set_function_source_hash(function_source_hash);
76+
true
77+
} else {
78+
false
79+
}
80+
}
81+
82+
fn add_coverage_counter(
83+
&mut self,
84+
instance: Instance<'tcx>,
6585
id: CounterValueReference,
6686
region: CodeRegion,
6787
) -> bool {
6888
if let Some(coverage_context) = self.coverage_context() {
6989
debug!(
70-
"adding counter to coverage_regions: instance={:?}, function_source_hash={}, id={:?}, \
71-
at {:?}",
72-
instance, function_source_hash, id, region,
90+
"adding counter to coverage_map: instance={:?}, id={:?}, region={:?}",
91+
instance, id, region,
7392
);
74-
let mut coverage_regions = coverage_context.function_coverage_map.borrow_mut();
75-
coverage_regions
93+
let mut coverage_map = coverage_context.function_coverage_map.borrow_mut();
94+
coverage_map
7695
.entry(instance)
7796
.or_insert_with(|| FunctionCoverage::new(self.tcx, instance))
78-
.add_counter(function_source_hash, id, region);
97+
.add_counter(id, region);
7998
true
8099
} else {
81100
false
82101
}
83102
}
84103

85-
fn add_counter_expression_region(
104+
fn add_coverage_counter_expression(
86105
&mut self,
87106
instance: Instance<'tcx>,
88-
id: InjectedExpressionIndex,
107+
id: InjectedExpressionId,
89108
lhs: ExpressionOperandId,
90109
op: Op,
91110
rhs: ExpressionOperandId,
92-
region: CodeRegion,
111+
region: Option<CodeRegion>,
93112
) -> bool {
94113
if let Some(coverage_context) = self.coverage_context() {
95114
debug!(
96-
"adding counter expression to coverage_regions: instance={:?}, id={:?}, {:?} {:?} {:?}, \
97-
at {:?}",
115+
"adding counter expression to coverage_map: instance={:?}, id={:?}, {:?} {:?} {:?}; \
116+
region: {:?}",
98117
instance, id, lhs, op, rhs, region,
99118
);
100-
let mut coverage_regions = coverage_context.function_coverage_map.borrow_mut();
101-
coverage_regions
119+
let mut coverage_map = coverage_context.function_coverage_map.borrow_mut();
120+
coverage_map
102121
.entry(instance)
103122
.or_insert_with(|| FunctionCoverage::new(self.tcx, instance))
104123
.add_counter_expression(id, lhs, op, rhs, region);
@@ -108,14 +127,14 @@ impl CoverageInfoBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
108127
}
109128
}
110129

111-
fn add_unreachable_region(&mut self, instance: Instance<'tcx>, region: CodeRegion) -> bool {
130+
fn add_coverage_unreachable(&mut self, instance: Instance<'tcx>, region: CodeRegion) -> bool {
112131
if let Some(coverage_context) = self.coverage_context() {
113132
debug!(
114-
"adding unreachable code to coverage_regions: instance={:?}, at {:?}",
133+
"adding unreachable code to coverage_map: instance={:?}, at {:?}",
115134
instance, region,
116135
);
117-
let mut coverage_regions = coverage_context.function_coverage_map.borrow_mut();
118-
coverage_regions
136+
let mut coverage_map = coverage_context.function_coverage_map.borrow_mut();
137+
coverage_map
119138
.entry(instance)
120139
.or_insert_with(|| FunctionCoverage::new(self.tcx, instance))
121140
.add_unreachable_region(region);

compiler/rustc_codegen_ssa/src/coverageinfo/ffi.rs

+6-6
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 {

0 commit comments

Comments
 (0)