Skip to content

Commit 8c7c84b

Browse files
committed
code coverage foundation for hash and num_counters
Replaced dummy values for hash and num_counters with computed values, and refactored InstrumentCoverage pass to simplify injecting more counters per function in upcoming versions. Improved usage documentation and error messaging.
1 parent 791cccc commit 8c7c84b

File tree

11 files changed

+230
-86
lines changed

11 files changed

+230
-86
lines changed

src/librustc_codegen_llvm/intrinsic.rs

Lines changed: 14 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,14 @@ use rustc_codegen_ssa::common::TypeKind;
1616
use rustc_codegen_ssa::glue;
1717
use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue};
1818
use rustc_codegen_ssa::mir::place::PlaceRef;
19+
use rustc_codegen_ssa::mir::FunctionCx;
1920
use rustc_codegen_ssa::traits::*;
2021
use rustc_codegen_ssa::MemFlags;
2122
use rustc_hir as hir;
2223
use rustc_middle::ty::layout::{FnAbiExt, HasTyCtxt};
2324
use rustc_middle::ty::{self, Ty};
2425
use rustc_middle::{bug, span_bug};
2526
use rustc_span::Span;
26-
use rustc_span::Symbol;
2727
use rustc_target::abi::{self, HasDataLayout, LayoutOf, Primitive};
2828
use rustc_target::spec::PanicStrategy;
2929

@@ -82,14 +82,14 @@ fn get_simple_intrinsic(cx: &CodegenCx<'ll, '_>, name: &str) -> Option<&'ll Valu
8282
}
8383

8484
impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
85-
fn codegen_intrinsic_call(
85+
fn codegen_intrinsic_call<'b, Bx: BuilderMethods<'b, 'tcx>>(
8686
&mut self,
87+
fx: &FunctionCx<'b, 'tcx, Bx>,
8788
instance: ty::Instance<'tcx>,
8889
fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
8990
args: &[OperandRef<'tcx, &'ll Value>],
9091
llresult: &'ll Value,
9192
span: Span,
92-
caller_instance: ty::Instance<'tcx>,
9393
) {
9494
let tcx = self.tcx;
9595
let callee_ty = instance.monomorphic_ty(tcx);
@@ -141,26 +141,17 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
141141
self.call(llfn, &[], None)
142142
}
143143
"count_code_region" => {
144-
if let ty::InstanceDef::Item(fn_def_id) = caller_instance.def {
145-
let caller_fn_path = tcx.def_path_str(fn_def_id);
146-
debug!(
147-
"count_code_region to llvm.instrprof.increment(fn_name={})",
148-
caller_fn_path
149-
);
150-
151-
// FIXME(richkadel): (1) Replace raw function name with mangled function name;
152-
// (2) Replace hardcoded `1234` in `hash` with a computed hash (as discussed in)
153-
// the MCP (compiler-team/issues/278); and replace the hardcoded `1` for
154-
// `num_counters` with the actual number of counters per function (when the
155-
// changes are made to inject more than one counter per function).
156-
let (fn_name, _len_val) = self.const_str(Symbol::intern(&caller_fn_path));
157-
let index = args[0].immediate();
158-
let hash = self.const_u64(1234);
159-
let num_counters = self.const_u32(1);
160-
self.instrprof_increment(fn_name, hash, num_counters, index)
161-
} else {
162-
bug!("intrinsic count_code_region: no src.instance");
163-
}
144+
let coverage_data = fx.mir.coverage_data.as_ref().unwrap();
145+
let mangled_fn = tcx.symbol_name(fx.instance);
146+
let (mangled_fn_name, _len_val) = self.const_str(mangled_fn.name);
147+
let hash = self.const_u64(coverage_data.hash);
148+
let index = args[0].immediate();
149+
let num_counters = self.const_u32(coverage_data.num_counters as u32);
150+
debug!(
151+
"count_code_region to LLVM intrinsic instrprof.increment(fn_name={}, hash={:?}, num_counters={:?}, index={:?})",
152+
mangled_fn.name, hash, index, num_counters
153+
);
154+
self.instrprof_increment(mangled_fn_name, hash, num_counters, index)
164155
}
165156
"va_start" => self.va_start(args[0].immediate()),
166157
"va_end" => self.va_end(args[0].immediate()),

src/librustc_codegen_ssa/mir/block.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -688,12 +688,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
688688
.collect();
689689

690690
bx.codegen_intrinsic_call(
691+
self,
691692
*instance.as_ref().unwrap(),
692693
&fn_abi,
693694
&args,
694695
dest,
695696
terminator.source_info.span,
696-
self.instance,
697697
);
698698

699699
if let ReturnDest::IndirectOperand(dst, _) = ret_dest {

src/librustc_codegen_ssa/mir/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@ use self::operand::{OperandRef, OperandValue};
2121

2222
/// Master context for codegenning from MIR.
2323
pub struct FunctionCx<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> {
24-
instance: Instance<'tcx>,
24+
pub instance: Instance<'tcx>,
2525

26-
mir: &'tcx mir::Body<'tcx>,
26+
pub mir: &'tcx mir::Body<'tcx>,
2727

2828
debug_context: Option<FunctionDebugContext<Bx::DIScope>>,
2929

src/librustc_codegen_ssa/traits/intrinsic.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
use super::BackendTypes;
22
use crate::mir::operand::OperandRef;
3+
use crate::mir::FunctionCx;
4+
use crate::traits::BuilderMethods;
35
use rustc_middle::ty::{self, Ty};
46
use rustc_span::Span;
57
use rustc_target::abi::call::FnAbi;
@@ -8,14 +10,14 @@ pub trait IntrinsicCallMethods<'tcx>: BackendTypes {
810
/// Remember to add all intrinsics here, in librustc_typeck/check/mod.rs,
911
/// and in libcore/intrinsics.rs; if you need access to any llvm intrinsics,
1012
/// add them to librustc_codegen_llvm/context.rs
11-
fn codegen_intrinsic_call(
13+
fn codegen_intrinsic_call<'a, Bx: BuilderMethods<'a, 'tcx>>(
1214
&mut self,
15+
fx: &FunctionCx<'a, 'tcx, Bx>,
1316
instance: ty::Instance<'tcx>,
1417
fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
1518
args: &[OperandRef<'tcx, Self::Value>],
1619
llresult: Self::Value,
1720
span: Span,
18-
caller_instance: ty::Instance<'tcx>,
1921
);
2022

2123
fn abort(&mut self);

src/librustc_metadata/locator.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -488,6 +488,8 @@ impl<'a> CrateLocator<'a> {
488488
&& self.triple != TargetTriple::from_triple(config::host_triple())
489489
{
490490
err.note(&format!("the `{}` target may not be installed", self.triple));
491+
} else if self.crate_name == sym::profiler_builtins {
492+
err.note(&"the compiler may have been built without `profiler = true`");
491493
}
492494
err.span_label(self.span, "can't find crate");
493495
err

src/librustc_middle/ich/hcx.rs

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,13 +67,15 @@ impl<'a> StableHashingContext<'a> {
6767
/// Don't use it for anything else or you'll run the risk of
6868
/// leaking data out of the tracking system.
6969
#[inline]
70-
pub fn new(
70+
fn new_with_or_without_spans(
7171
sess: &'a Session,
7272
krate: &'a hir::Crate<'a>,
7373
definitions: &'a Definitions,
7474
cstore: &'a dyn CrateStore,
75+
always_ignore_spans: bool,
7576
) -> Self {
76-
let hash_spans_initial = !sess.opts.debugging_opts.incremental_ignore_spans;
77+
let hash_spans_initial =
78+
!always_ignore_spans && !sess.opts.debugging_opts.incremental_ignore_spans;
7779

7880
StableHashingContext {
7981
sess,
@@ -88,6 +90,33 @@ impl<'a> StableHashingContext<'a> {
8890
}
8991
}
9092

93+
#[inline]
94+
pub fn new(
95+
sess: &'a Session,
96+
krate: &'a hir::Crate<'a>,
97+
definitions: &'a Definitions,
98+
cstore: &'a dyn CrateStore,
99+
) -> Self {
100+
Self::new_with_or_without_spans(
101+
sess,
102+
krate,
103+
definitions,
104+
cstore,
105+
/*always_ignore_spans=*/ false,
106+
)
107+
}
108+
109+
#[inline]
110+
pub fn ignore_spans(
111+
sess: &'a Session,
112+
krate: &'a hir::Crate<'a>,
113+
definitions: &'a Definitions,
114+
cstore: &'a dyn CrateStore,
115+
) -> Self {
116+
let always_ignore_spans = true;
117+
Self::new_with_or_without_spans(sess, krate, definitions, cstore, always_ignore_spans)
118+
}
119+
91120
#[inline]
92121
pub fn sess(&self) -> &'a Session {
93122
self.sess

src/librustc_middle/mir/mod.rs

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,19 @@ 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: usize,
102+
}
103+
91104
/// The lowered representation of a single function.
92105
#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable, TypeFoldable)]
93106
pub struct Body<'tcx> {
@@ -164,13 +177,17 @@ pub struct Body<'tcx> {
164177
/// The user may be writing e.g. `&[(SOME_CELL, 42)][i].1` and this would get promoted, because
165178
/// we'd statically know that no thing with interior mutability will ever be available to the
166179
/// user without some serious unsafe code. Now this means that our promoted is actually
167-
/// `&[(SOME_CELL, 42)]` and the MIR using it will do the `&promoted[i].1` projection because the
168-
/// index may be a runtime value. Such a promoted value is illegal because it has reachable
180+
/// `&[(SOME_CELL, 42)]` and the MIR using it will do the `&promoted[i].1` projection because
181+
/// the index may be a runtime value. Such a promoted value is illegal because it has reachable
169182
/// interior mutability. This flag just makes this situation very obvious where the previous
170183
/// implementation without the flag hid this situation silently.
171184
/// FIXME(oli-obk): rewrite the promoted during promotion to eliminate the cell components.
172185
pub ignore_interior_mut_in_const_validation: bool,
173186

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+
174191
predecessor_cache: PredecessorCache,
175192
}
176193

@@ -211,6 +228,7 @@ impl<'tcx> Body<'tcx> {
211228
required_consts: Vec::new(),
212229
ignore_interior_mut_in_const_validation: false,
213230
control_flow_destroyed,
231+
coverage_data: None,
214232
predecessor_cache: PredecessorCache::new(),
215233
}
216234
}
@@ -238,6 +256,7 @@ impl<'tcx> Body<'tcx> {
238256
generator_kind: None,
239257
var_debug_info: Vec::new(),
240258
ignore_interior_mut_in_const_validation: false,
259+
coverage_data: None,
241260
predecessor_cache: PredecessorCache::new(),
242261
}
243262
}

src/librustc_middle/ty/context.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1284,6 +1284,13 @@ impl<'tcx> TyCtxt<'tcx> {
12841284
StableHashingContext::new(self.sess, krate, self.definitions, &*self.cstore)
12851285
}
12861286

1287+
#[inline(always)]
1288+
pub fn create_no_span_stable_hashing_context(self) -> StableHashingContext<'tcx> {
1289+
let krate = self.gcx.untracked_crate;
1290+
1291+
StableHashingContext::ignore_spans(self.sess, krate, self.definitions, &*self.cstore)
1292+
}
1293+
12871294
// This method makes sure that we have a DepNode and a Fingerprint for
12881295
// every upstream crate. It needs to be called once right after the tcx is
12891296
// created.

0 commit comments

Comments
 (0)