Skip to content

Commit 20aba8f

Browse files
committed
added test, Operand::const_from_scalar, require_lang_item, & comments
Addresses feedback from @oli-obk (Thanks!)
1 parent 46ebd57 commit 20aba8f

File tree

6 files changed

+186
-37
lines changed

6 files changed

+186
-37
lines changed

src/librustc_middle/mir/mod.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ use rustc_macros::HashStable;
2929
use rustc_serialize::{Decodable, Encodable};
3030
use rustc_span::symbol::Symbol;
3131
use rustc_span::{Span, DUMMY_SP};
32+
use rustc_target::abi;
3233
use rustc_target::asm::InlineAsmRegOrRegClass;
3334
use std::borrow::Cow;
3435
use std::fmt::{self, Debug, Display, Formatter, Write};
@@ -2218,6 +2219,33 @@ impl<'tcx> Operand<'tcx> {
22182219
})
22192220
}
22202221

2222+
/// Convenience helper to make a literal-like constant from a given scalar value.
2223+
/// Since this is used to synthesize MIR, assumes `user_ty` is None.
2224+
pub fn const_from_scalar(
2225+
tcx: TyCtxt<'tcx>,
2226+
ty: Ty<'tcx>,
2227+
val: Scalar,
2228+
span: Span,
2229+
) -> Operand<'tcx> {
2230+
debug_assert!({
2231+
let param_env_and_ty = ty::ParamEnv::empty().and(ty);
2232+
let type_size = tcx
2233+
.layout_of(param_env_and_ty)
2234+
.unwrap_or_else(|e| panic!("could not compute layout for {:?}: {:?}", ty, e))
2235+
.size;
2236+
let scalar_size = abi::Size::from_bytes(match val {
2237+
Scalar::Raw { size, .. } => size,
2238+
_ => panic!("Invalid scalar type {:?}", val),
2239+
});
2240+
scalar_size == type_size
2241+
});
2242+
Operand::Constant(box Constant {
2243+
span,
2244+
user_ty: None,
2245+
literal: ty::Const::from_scalar(tcx, val, ty),
2246+
})
2247+
}
2248+
22212249
pub fn to_copy(&self) -> Self {
22222250
match *self {
22232251
Operand::Copy(_) | Operand::Constant(_) => self.clone(),

src/librustc_mir/interpret/intrinsics.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
389389
);
390390
self.copy_op(self.operand_index(args[0], index)?, dest)?;
391391
}
392+
// FIXME(#73156): Handle source code coverage in const eval
392393
sym::count_code_region => (),
393394
_ => return Ok(false),
394395
}

src/librustc_mir/transform/instrument_coverage.rs

Lines changed: 15 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,17 @@
11
use crate::transform::{MirPass, MirSource};
22
use crate::util::patch::MirPatch;
3+
use rustc_hir::lang_items;
34
use rustc_middle::mir::interpret::Scalar;
45
use rustc_middle::mir::*;
56
use rustc_middle::ty;
6-
use rustc_middle::ty::Ty;
77
use rustc_middle::ty::TyCtxt;
88
use rustc_span::def_id::DefId;
99
use rustc_span::Span;
10-
use rustc_target::abi;
1110

11+
/// Inserts call to count_code_region() as a placeholder to be replaced during code generation with
12+
/// the intrinsic llvm.instrprof.increment.
1213
pub struct InstrumentCoverage;
1314

14-
/**
15-
* Inserts call to count_code_region() as a placeholder to be replaced during code generation with
16-
* the intrinsic llvm.instrprof.increment.
17-
*/
18-
1915
impl<'tcx> MirPass<'tcx> for InstrumentCoverage {
2016
fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) {
2117
if tcx.sess.opts.debugging_opts.instrument_coverage {
@@ -34,10 +30,17 @@ const INIT_FUNCTION_COUNTER: u32 = 0;
3430
pub fn instrument_coverage<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
3531
let span = body.span.shrink_to_lo();
3632

37-
let count_code_region_fn =
38-
function_handle(tcx, span, tcx.lang_items().count_code_region_fn().unwrap());
39-
let counter_index =
40-
const_int_operand(tcx, span, tcx.types.u32, Scalar::from_u32(INIT_FUNCTION_COUNTER));
33+
let count_code_region_fn = function_handle(
34+
tcx,
35+
tcx.require_lang_item(lang_items::CountCodeRegionFnLangItem, None),
36+
span,
37+
);
38+
let counter_index = Operand::const_from_scalar(
39+
tcx,
40+
tcx.types.u32,
41+
Scalar::from_u32(INIT_FUNCTION_COUNTER),
42+
span,
43+
);
4144

4245
let mut patch = MirPatch::new(body);
4346

@@ -68,38 +71,13 @@ pub fn instrument_coverage<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
6871
body.basic_blocks_mut().swap(next_block, new_block);
6972
}
7073

71-
fn function_handle<'tcx>(tcx: TyCtxt<'tcx>, span: Span, fn_def_id: DefId) -> Operand<'tcx> {
74+
fn function_handle<'tcx>(tcx: TyCtxt<'tcx>, fn_def_id: DefId, span: Span) -> Operand<'tcx> {
7275
let ret_ty = tcx.fn_sig(fn_def_id).output();
7376
let ret_ty = ret_ty.no_bound_vars().unwrap();
7477
let substs = tcx.mk_substs(::std::iter::once(ty::subst::GenericArg::from(ret_ty)));
7578
Operand::function_handle(tcx, fn_def_id, substs, span)
7679
}
7780

78-
fn const_int_operand<'tcx>(
79-
tcx: TyCtxt<'tcx>,
80-
span: Span,
81-
ty: Ty<'tcx>,
82-
val: Scalar,
83-
) -> Operand<'tcx> {
84-
debug_assert!({
85-
let param_env_and_ty = ty::ParamEnv::empty().and(ty);
86-
let type_size = tcx
87-
.layout_of(param_env_and_ty)
88-
.unwrap_or_else(|e| panic!("could not compute layout for {:?}: {:?}", ty, e))
89-
.size;
90-
let scalar_size = abi::Size::from_bytes(match val {
91-
Scalar::Raw { size, .. } => size,
92-
_ => panic!("Invalid scalar type {:?}", val),
93-
});
94-
scalar_size == type_size
95-
});
96-
Operand::Constant(box Constant {
97-
span,
98-
user_ty: None,
99-
literal: ty::Const::from_scalar(tcx, val, ty),
100-
})
101-
}
102-
10381
fn placeholder_block<'tcx>(source_info: SourceInfo) -> BasicBlockData<'tcx> {
10482
BasicBlockData {
10583
statements: vec![],
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Test that the initial version of Rust coverage injects count_code_region() placeholder calls,
2+
// at the top of each function. The placeholders are later converted into LLVM instrprof.increment
3+
// intrinsics, during codegen.
4+
5+
// compile-flags: -Zinstrument-coverage
6+
// EMIT_MIR rustc.main.InstrumentCoverage.diff
7+
// EMIT_MIR rustc.bar.InstrumentCoverage.diff
8+
fn main() {
9+
loop {
10+
if bar() {
11+
break;
12+
}
13+
}
14+
}
15+
16+
#[inline(never)]
17+
fn bar() -> bool {
18+
true
19+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
- // MIR for `bar` before InstrumentCoverage
2+
+ // MIR for `bar` after InstrumentCoverage
3+
4+
fn bar() -> bool {
5+
let mut _0: bool; // return place in scope 0 at $DIR/instrument_coverage.rs:17:13: 17:17
6+
+ let mut _1: (); // in scope 0 at $DIR/instrument_coverage.rs:17:1: 19:2
7+
8+
bb0: {
9+
+ StorageLive(_1); // scope 0 at $DIR/instrument_coverage.rs:17:1: 19:2
10+
+ _1 = const std::intrinsics::count_code_region(const 0u32) -> bb2; // scope 0 at $DIR/instrument_coverage.rs:17:1: 19:2
11+
+ // ty::Const
12+
+ // + ty: unsafe extern "rust-intrinsic" fn(u32) {std::intrinsics::count_code_region}
13+
+ // + val: Value(Scalar(<ZST>))
14+
+ // mir::Constant
15+
+ // + span: $DIR/instrument_coverage.rs:17:1: 17:1
16+
+ // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(u32) {std::intrinsics::count_code_region}, val: Value(Scalar(<ZST>)) }
17+
+ // ty::Const
18+
+ // + ty: u32
19+
+ // + val: Value(Scalar(0x00000000))
20+
+ // mir::Constant
21+
+ // + span: $DIR/instrument_coverage.rs:17:1: 17:1
22+
+ // + literal: Const { ty: u32, val: Value(Scalar(0x00000000)) }
23+
+ }
24+
+
25+
+ bb1 (cleanup): {
26+
+ resume; // scope 0 at $DIR/instrument_coverage.rs:17:1: 19:2
27+
+ }
28+
+
29+
+ bb2: {
30+
+ StorageDead(_1); // scope 0 at $DIR/instrument_coverage.rs:18:5: 18:9
31+
_0 = const true; // scope 0 at $DIR/instrument_coverage.rs:18:5: 18:9
32+
// ty::Const
33+
// + ty: bool
34+
// + val: Value(Scalar(0x01))
35+
// mir::Constant
36+
// + span: $DIR/instrument_coverage.rs:18:5: 18:9
37+
// + literal: Const { ty: bool, val: Value(Scalar(0x01)) }
38+
return; // scope 0 at $DIR/instrument_coverage.rs:19:2: 19:2
39+
}
40+
}
41+
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
- // MIR for `main` before InstrumentCoverage
2+
+ // MIR for `main` after InstrumentCoverage
3+
4+
fn main() -> () {
5+
let mut _0: (); // return place in scope 0 at $DIR/instrument_coverage.rs:8:11: 8:11
6+
let mut _1: (); // in scope 0 at $DIR/instrument_coverage.rs:8:1: 14:2
7+
let mut _2: bool; // in scope 0 at $DIR/instrument_coverage.rs:10:12: 10:17
8+
let mut _3: !; // in scope 0 at $DIR/instrument_coverage.rs:10:18: 12:10
9+
+ let mut _4: (); // in scope 0 at $DIR/instrument_coverage.rs:8:1: 14:2
10+
11+
bb0: {
12+
- falseUnwind -> [real: bb1, cleanup: bb6]; // scope 0 at $DIR/instrument_coverage.rs:9:5: 13:6
13+
+ StorageLive(_4); // scope 0 at $DIR/instrument_coverage.rs:8:1: 14:2
14+
+ _4 = const std::intrinsics::count_code_region(const 0u32) -> bb7; // scope 0 at $DIR/instrument_coverage.rs:8:1: 14:2
15+
+ // ty::Const
16+
+ // + ty: unsafe extern "rust-intrinsic" fn(u32) {std::intrinsics::count_code_region}
17+
+ // + val: Value(Scalar(<ZST>))
18+
+ // mir::Constant
19+
+ // + span: $DIR/instrument_coverage.rs:8:1: 8:1
20+
+ // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(u32) {std::intrinsics::count_code_region}, val: Value(Scalar(<ZST>)) }
21+
+ // ty::Const
22+
+ // + ty: u32
23+
+ // + val: Value(Scalar(0x00000000))
24+
+ // mir::Constant
25+
+ // + span: $DIR/instrument_coverage.rs:8:1: 8:1
26+
+ // + literal: Const { ty: u32, val: Value(Scalar(0x00000000)) }
27+
}
28+
29+
bb1: {
30+
StorageLive(_2); // scope 0 at $DIR/instrument_coverage.rs:10:12: 10:17
31+
_2 = const bar() -> [return: bb2, unwind: bb6]; // scope 0 at $DIR/instrument_coverage.rs:10:12: 10:17
32+
// ty::Const
33+
// + ty: fn() -> bool {bar}
34+
// + val: Value(Scalar(<ZST>))
35+
// mir::Constant
36+
// + span: $DIR/instrument_coverage.rs:10:12: 10:15
37+
// + literal: Const { ty: fn() -> bool {bar}, val: Value(Scalar(<ZST>)) }
38+
}
39+
40+
bb2: {
41+
FakeRead(ForMatchedPlace, _2); // scope 0 at $DIR/instrument_coverage.rs:10:12: 10:17
42+
switchInt(_2) -> [false: bb4, otherwise: bb3]; // scope 0 at $DIR/instrument_coverage.rs:10:9: 12:10
43+
}
44+
45+
bb3: {
46+
falseEdges -> [real: bb5, imaginary: bb4]; // scope 0 at $DIR/instrument_coverage.rs:10:9: 12:10
47+
}
48+
49+
bb4: {
50+
_1 = const (); // scope 0 at $DIR/instrument_coverage.rs:10:9: 12:10
51+
// ty::Const
52+
// + ty: ()
53+
// + val: Value(Scalar(<ZST>))
54+
// mir::Constant
55+
// + span: $DIR/instrument_coverage.rs:10:9: 12:10
56+
// + literal: Const { ty: (), val: Value(Scalar(<ZST>)) }
57+
StorageDead(_2); // scope 0 at $DIR/instrument_coverage.rs:13:5: 13:6
58+
goto -> bb0; // scope 0 at $DIR/instrument_coverage.rs:9:5: 13:6
59+
}
60+
61+
bb5: {
62+
_0 = const (); // scope 0 at $DIR/instrument_coverage.rs:11:13: 11:18
63+
// ty::Const
64+
// + ty: ()
65+
// + val: Value(Scalar(<ZST>))
66+
// mir::Constant
67+
// + span: $DIR/instrument_coverage.rs:11:13: 11:18
68+
// + literal: Const { ty: (), val: Value(Scalar(<ZST>)) }
69+
StorageDead(_2); // scope 0 at $DIR/instrument_coverage.rs:13:5: 13:6
70+
return; // scope 0 at $DIR/instrument_coverage.rs:14:2: 14:2
71+
}
72+
73+
bb6 (cleanup): {
74+
resume; // scope 0 at $DIR/instrument_coverage.rs:8:1: 14:2
75+
+ }
76+
+
77+
+ bb7: {
78+
+ StorageDead(_4); // scope 0 at $DIR/instrument_coverage.rs:9:5: 13:6
79+
+ falseUnwind -> [real: bb1, cleanup: bb6]; // scope 0 at $DIR/instrument_coverage.rs:9:5: 13:6
80+
}
81+
}
82+

0 commit comments

Comments
 (0)