Skip to content

Commit 08ec4cb

Browse files
committed
moves coverage data computation from pass to query
1 parent 994d9d0 commit 08ec4cb

File tree

5 files changed

+56
-56
lines changed

5 files changed

+56
-56
lines changed

src/librustc_codegen_llvm/intrinsic.rs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -140,18 +140,15 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
140140
self.call(llfn, &[], None)
141141
}
142142
"count_code_region" => {
143-
let coverage_data = tcx
144-
.coverage_data(caller_instance.def_id())
145-
.as_ref()
146-
.expect("LLVM intrinsic count_code_region call has associated coverage_data");
143+
let coverage_data = tcx.coverage_data(caller_instance.def_id());
147144
let mangled_fn = tcx.symbol_name(caller_instance);
148145
let (mangled_fn_name, _len_val) = self.const_str(mangled_fn.name);
149146
let hash = self.const_u64(coverage_data.hash);
150-
let index = args[0].immediate();
151147
let num_counters = self.const_u32(coverage_data.num_counters);
148+
let index = args[0].immediate();
152149
debug!(
153150
"count_code_region to LLVM intrinsic instrprof.increment(fn_name={}, hash={:?}, num_counters={:?}, index={:?})",
154-
mangled_fn.name, hash, index, num_counters
151+
mangled_fn.name, hash, num_counters, index
155152
);
156153
self.instrprof_increment(mangled_fn_name, hash, num_counters, index)
157154
}

src/librustc_middle/mir/mod.rs

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -88,19 +88,6 @@ impl MirPhase {
8888
}
8989
}
9090

91-
/// Coverage data computed by the `InstrumentCoverage` MIR pass, when compiling with
92-
/// `-Zinstrument_coverage`.
93-
#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable, TypeFoldable)]
94-
pub struct CoverageData {
95-
/// A hash value that can be used by the consumer of the coverage profile data to detect
96-
/// changes to the instrumented source of the associated MIR body (typically, for an
97-
/// individual function).
98-
pub hash: u64,
99-
100-
/// The total number of coverage region counters added to this MIR Body.
101-
pub num_counters: u32,
102-
}
103-
10491
/// The lowered representation of a single function.
10592
#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable, TypeFoldable)]
10693
pub struct Body<'tcx> {
@@ -184,10 +171,6 @@ pub struct Body<'tcx> {
184171
/// FIXME(oli-obk): rewrite the promoted during promotion to eliminate the cell components.
185172
pub ignore_interior_mut_in_const_validation: bool,
186173

187-
/// If compiling with `-Zinstrument_coverage`, the `InstrumentCoverage` pass stores summary
188-
/// information associated with the MIR, used in code generation of the coverage counters.
189-
pub coverage_data: Option<CoverageData>,
190-
191174
predecessor_cache: PredecessorCache,
192175
}
193176

@@ -228,7 +211,6 @@ impl<'tcx> Body<'tcx> {
228211
required_consts: Vec::new(),
229212
ignore_interior_mut_in_const_validation: false,
230213
control_flow_destroyed,
231-
coverage_data: None,
232214
predecessor_cache: PredecessorCache::new(),
233215
}
234216
}
@@ -256,7 +238,6 @@ impl<'tcx> Body<'tcx> {
256238
generator_kind: None,
257239
var_debug_info: Vec::new(),
258240
ignore_interior_mut_in_const_validation: false,
259-
coverage_data: None,
260241
predecessor_cache: PredecessorCache::new(),
261242
}
262243
}
@@ -2938,3 +2919,18 @@ impl Location {
29382919
}
29392920
}
29402921
}
2922+
2923+
/// Coverage data associated with each function (MIR) instrumented with coverage counters, when
2924+
/// compiled with `-Zinstrument_coverage`. The query `tcx.coverage_data(DefId)` computes these
2925+
/// values on demand (during code generation). This query is only valid after executing the MIR pass
2926+
/// `InstrumentCoverage`.
2927+
#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
2928+
pub struct CoverageData {
2929+
/// A hash value that can be used by the consumer of the coverage profile data to detect
2930+
/// changes to the instrumented source of the associated MIR body (typically, for an
2931+
/// individual function).
2932+
pub hash: u64,
2933+
2934+
/// The total number of coverage region counters added to the MIR `Body`.
2935+
pub num_counters: u32,
2936+
}

src/librustc_middle/query/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ rustc_queries! {
214214
cache_on_disk_if { key.is_local() }
215215
}
216216

217-
query coverage_data(key: DefId) -> Option<mir::CoverageData> {
217+
query coverage_data(key: DefId) -> mir::CoverageData {
218218
desc { |tcx| "retrieving coverage data from MIR for `{}`", tcx.def_path_str(key) }
219219
storage(ArenaCacheSelector<'tcx>)
220220
cache_on_disk_if { key.is_local() }

src/librustc_mir/transform/instrument_coverage.rs

Lines changed: 35 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,12 @@ use rustc_middle::hir;
77
use rustc_middle::ich::StableHashingContext;
88
use rustc_middle::mir::interpret::Scalar;
99
use rustc_middle::mir::{
10-
self, BasicBlock, BasicBlockData, CoverageData, Operand, Place, SourceInfo, StatementKind,
11-
Terminator, TerminatorKind, START_BLOCK,
10+
self, traversal, BasicBlock, BasicBlockData, CoverageData, Operand, Place, SourceInfo,
11+
StatementKind, Terminator, TerminatorKind, START_BLOCK,
1212
};
1313
use rustc_middle::ty;
14+
use rustc_middle::ty::query::Providers;
15+
use rustc_middle::ty::FnDef;
1416
use rustc_middle::ty::TyCtxt;
1517
use rustc_span::def_id::DefId;
1618
use rustc_span::Span;
@@ -19,6 +21,31 @@ use rustc_span::Span;
1921
/// the intrinsic llvm.instrprof.increment.
2022
pub struct InstrumentCoverage;
2123

24+
/// The `query` provider for `CoverageData`, requested by `codegen_intrinsic_call()` when
25+
/// constructing the arguments for `llvm.instrprof.increment`.
26+
pub(crate) fn provide(providers: &mut Providers<'_>) {
27+
providers.coverage_data = |tcx, def_id| {
28+
let body = tcx.optimized_mir(def_id);
29+
let count_code_region_fn =
30+
tcx.require_lang_item(lang_items::CountCodeRegionFnLangItem, None);
31+
let mut num_counters: u32 = 0;
32+
for (_, data) in traversal::preorder(body) {
33+
if let Some(terminator) = &data.terminator {
34+
if let TerminatorKind::Call { func: Operand::Constant(func), .. } = &terminator.kind
35+
{
36+
if let FnDef(called_fn_def_id, _) = func.literal.ty.kind {
37+
if called_fn_def_id == count_code_region_fn {
38+
num_counters += 1;
39+
}
40+
}
41+
}
42+
}
43+
}
44+
let hash = if num_counters > 0 { hash_mir_source(tcx, def_id) } else { 0 };
45+
CoverageData { num_counters, hash }
46+
};
47+
}
48+
2249
struct Instrumentor<'tcx> {
2350
tcx: TyCtxt<'tcx>,
2451
num_counters: u32,
@@ -30,20 +57,12 @@ impl<'tcx> MirPass<'tcx> for InstrumentCoverage {
3057
// If the InstrumentCoverage pass is called on promoted MIRs, skip them.
3158
// See: https://github.com/rust-lang/rust/pull/73011#discussion_r438317601
3259
if src.promoted.is_none() {
33-
assert!(mir_body.coverage_data.is_none());
34-
35-
let hash = hash_mir_source(tcx, &src);
36-
3760
debug!(
38-
"instrumenting {:?}, hash: {}, span: {}",
61+
"instrumenting {:?}, span: {}",
3962
src.def_id(),
40-
hash,
4163
tcx.sess.source_map().span_to_string(mir_body.span)
4264
);
43-
44-
let num_counters = Instrumentor::new(tcx).inject_counters(mir_body);
45-
46-
mir_body.coverage_data = Some(CoverageData { hash, num_counters });
65+
Instrumentor::new(tcx).inject_counters(mir_body);
4766
}
4867
}
4968
}
@@ -60,15 +79,13 @@ impl<'tcx> Instrumentor<'tcx> {
6079
next
6180
}
6281

63-
fn inject_counters(&mut self, mir_body: &mut mir::Body<'tcx>) -> u32 {
82+
fn inject_counters(&mut self, mir_body: &mut mir::Body<'tcx>) {
6483
// FIXME(richkadel): As a first step, counters are only injected at the top of each
6584
// function. The complete solution will inject counters at each conditional code branch.
6685
let top_of_function = START_BLOCK;
6786
let entire_function = mir_body.span;
6887

6988
self.inject_counter(mir_body, top_of_function, entire_function);
70-
71-
self.num_counters
7289
}
7390

7491
fn inject_counter(
@@ -138,14 +155,9 @@ fn placeholder_block(span: Span) -> BasicBlockData<'tcx> {
138155
}
139156
}
140157

141-
fn hash_mir_source<'tcx>(tcx: TyCtxt<'tcx>, src: &MirSource<'tcx>) -> u64 {
142-
let fn_body_id = match tcx.hir().get_if_local(src.def_id()) {
143-
Some(node) => match hir::map::associated_body(node) {
144-
Some(body_id) => body_id,
145-
_ => bug!("instrumented MirSource does not include a function body: {:?}", node),
146-
},
147-
None => bug!("instrumented MirSource is not local: {:?}", src),
148-
};
158+
fn hash_mir_source<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> u64 {
159+
let hir_node = tcx.hir().get_if_local(def_id).expect("DefId is local");
160+
let fn_body_id = hir::map::associated_body(hir_node).expect("HIR node is a function with body");
149161
let hir_body = tcx.hir().body(fn_body_id);
150162
let mut hcx = tcx.create_no_span_stable_hashing_context();
151163
hash(&mut hcx, &hir_body.value).to_smaller_hash()

src/librustc_mir/transform/mod.rs

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
66
use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
77
use rustc_index::vec::IndexVec;
88
use rustc_middle::mir::visit::Visitor as _;
9-
use rustc_middle::mir::{traversal, Body, ConstQualifs, CoverageData, MirPhase, Promoted};
9+
use rustc_middle::mir::{traversal, Body, ConstQualifs, MirPhase, Promoted};
1010
use rustc_middle::ty::query::Providers;
1111
use rustc_middle::ty::steal::Steal;
1212
use rustc_middle::ty::{InstanceDef, TyCtxt, TypeFoldable};
@@ -53,10 +53,10 @@ pub(crate) fn provide(providers: &mut Providers<'_>) {
5353
mir_drops_elaborated_and_const_checked,
5454
optimized_mir,
5555
is_mir_available,
56-
coverage_data,
5756
promoted_mir,
5857
..*providers
5958
};
59+
instrument_coverage::provide(providers);
6060
}
6161

6262
fn is_mir_available(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
@@ -423,11 +423,6 @@ fn run_optimization_passes<'tcx>(
423423
);
424424
}
425425

426-
fn coverage_data(tcx: TyCtxt<'_>, def_id: DefId) -> Option<CoverageData> {
427-
let body = tcx.optimized_mir(def_id);
428-
body.coverage_data.clone()
429-
}
430-
431426
fn optimized_mir(tcx: TyCtxt<'_>, def_id: DefId) -> Body<'_> {
432427
if tcx.is_constructor(def_id) {
433428
// There's no reason to run all of the MIR passes on constructors when

0 commit comments

Comments
 (0)