Skip to content

Commit 5068ae1

Browse files
committed
[WIP] injects llvm intrinsic instrprof.increment for coverage reports
This initial version only injects counters at the top of each function. Rust Coverage will require injecting additional counters at each conditional code branch.
1 parent 395256a commit 5068ae1

Some content is hidden

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

52 files changed

+2561
-5
lines changed

src/libcore/intrinsics.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1943,6 +1943,15 @@ extern "rust-intrinsic" {
19431943
pub fn miri_start_panic(payload: *mut u8) -> !;
19441944
}
19451945

1946+
#[cfg(not(bootstrap))]
1947+
#[cfg_attr(not(bootstrap), lang = "count_code_region")]
1948+
pub fn count_code_region(_index: u32) {
1949+
#[cfg_attr(not(bootstrap), allow(unused_unsafe))] // remove `unsafe` on bootstrap bump
1950+
unsafe {
1951+
abort()
1952+
}
1953+
}
1954+
19461955
// Some functions are defined here because they accidentally got made
19471956
// available in this module on stable. See <https://github.com/rust-lang/rust/issues/15702>.
19481957
// (`transmute` also falls into this category, but it cannot be wrapped due to the

src/librustc_codegen_llvm/builder.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -997,6 +997,33 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
997997
self.call_lifetime_intrinsic("llvm.lifetime.end.p0i8", ptr, size);
998998
}
999999

1000+
fn instrprof_increment(
1001+
&mut self,
1002+
fn_name: &'ll Value,
1003+
hash: &'ll Value,
1004+
num_counters: &'ll Value,
1005+
index: &'ll Value,
1006+
) -> &'ll Value {
1007+
debug!(
1008+
"instrprof_increment() with args ({:?}, {:?}, {:?}, {:?})",
1009+
fn_name, hash, num_counters, index
1010+
);
1011+
1012+
let llfn = unsafe { llvm::LLVMRustGetInstrprofIncrementIntrinsic(self.cx().llmod) };
1013+
let args = &[fn_name, hash, num_counters, index];
1014+
let args = self.check_call("call", llfn, args);
1015+
1016+
unsafe {
1017+
llvm::LLVMRustBuildCall(
1018+
self.llbuilder,
1019+
llfn,
1020+
args.as_ptr() as *const &llvm::Value,
1021+
args.len() as c_uint,
1022+
None,
1023+
)
1024+
}
1025+
}
1026+
10001027
fn call(
10011028
&mut self,
10021029
llfn: &'ll Value,

src/librustc_codegen_llvm/context.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -749,6 +749,8 @@ impl CodegenCx<'b, 'tcx> {
749749
ifn!("llvm.lifetime.start.p0i8", fn(t_i64, i8p) -> void);
750750
ifn!("llvm.lifetime.end.p0i8", fn(t_i64, i8p) -> void);
751751

752+
ifn!("llvm.instrprof.increment", fn(i8p, t_i64, t_i32, t_i32) -> void);
753+
752754
ifn!("llvm.expect.i1", fn(i1, i1) -> i1);
753755
ifn!("llvm.eh.typeid.for", fn(i8p) -> t_i32);
754756
ifn!("llvm.localescape", fn(...) -> void);

src/librustc_codegen_llvm/intrinsic.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ use crate::type_of::LayoutLlvmExt;
77
use crate::va_arg::emit_va_arg;
88
use crate::value::Value;
99

10+
use log::debug;
11+
1012
use rustc_ast::ast;
1113
use rustc_codegen_ssa::base::{compare_simd_types, to_immediate, wants_msvc_seh};
1214
use rustc_codegen_ssa::common::span_invalid_monomorphization_error;
@@ -21,6 +23,7 @@ use rustc_middle::ty::layout::{FnAbiExt, HasTyCtxt};
2123
use rustc_middle::ty::{self, Ty};
2224
use rustc_middle::{bug, span_bug};
2325
use rustc_span::Span;
26+
use rustc_span::Symbol;
2427
use rustc_target::abi::{self, HasDataLayout, LayoutOf, Primitive};
2528
use rustc_target::spec::PanicStrategy;
2629

@@ -86,6 +89,7 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
8689
args: &[OperandRef<'tcx, &'ll Value>],
8790
llresult: &'ll Value,
8891
span: Span,
92+
caller_instance: ty::Instance<'tcx>,
8993
) {
9094
let tcx = self.tcx;
9195
let callee_ty = instance.monomorphic_ty(tcx);
@@ -136,6 +140,23 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
136140
let llfn = self.get_intrinsic(&("llvm.debugtrap"));
137141
self.call(llfn, &[], None)
138142
}
143+
"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+
let (fn_name, _len_val) = self.const_str(Symbol::intern(&caller_fn_path));
152+
let index = args[0].immediate();
153+
let hash = self.const_u64(1234);
154+
let num_counters = self.const_u32(1);
155+
self.instrprof_increment(fn_name, hash, num_counters, index)
156+
} else {
157+
bug!("intrinsic count_code_region: no src.instance");
158+
}
159+
}
139160
"va_start" => self.va_start(args[0].immediate()),
140161
"va_end" => self.va_end(args[0].immediate()),
141162
"va_copy" => {

src/librustc_codegen_llvm/llvm/ffi.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1360,6 +1360,7 @@ extern "C" {
13601360

13611361
// Miscellaneous instructions
13621362
pub fn LLVMBuildPhi(B: &Builder<'a>, Ty: &'a Type, Name: *const c_char) -> &'a Value;
1363+
pub fn LLVMRustGetInstrprofIncrementIntrinsic(M: &Module) -> &'a Value;
13631364
pub fn LLVMRustBuildCall(
13641365
B: &Builder<'a>,
13651366
Fn: &'a Value,

src/librustc_codegen_ssa/back/write.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,12 @@ impl ModuleConfig {
175175
if sess.opts.debugging_opts.profile && !is_compiler_builtins {
176176
passes.push("insert-gcov-profiling".to_owned());
177177
}
178+
179+
// The rustc option `-Zinstrument_coverage` injects intrinsic calls to
180+
// `llvm.instrprof.increment()`, which requires the LLVM `instrprof` pass.
181+
if sess.opts.debugging_opts.instrument_coverage {
182+
passes.push("instrprof".to_owned());
183+
}
178184
passes
179185
},
180186
vec![]

src/librustc_codegen_ssa/mir/block.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -566,7 +566,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
566566

567567
// Handle intrinsics old codegen wants Expr's for, ourselves.
568568
let intrinsic = match def {
569-
Some(ty::InstanceDef::Intrinsic(def_id)) => Some(bx.tcx().item_name(def_id).as_str()),
569+
Some(ty::InstanceDef::Intrinsic(def_id))
570+
| Some(ty::InstanceDef::InjectedCode(def_id)) => {
571+
Some(bx.tcx().item_name(def_id).as_str())
572+
}
570573
_ => None,
571574
};
572575
let intrinsic = intrinsic.as_ref().map(|s| &s[..]);
@@ -693,6 +696,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
693696
&args,
694697
dest,
695698
terminator.source_info.span,
699+
self.instance,
696700
);
697701

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

src/librustc_codegen_ssa/traits/builder.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,14 @@ pub trait BuilderMethods<'a, 'tcx>:
260260
/// Called for `StorageDead`
261261
fn lifetime_end(&mut self, ptr: Self::Value, size: Size);
262262

263+
fn instrprof_increment(
264+
&mut self,
265+
fn_name: Self::Value,
266+
hash: Self::Value,
267+
num_counters: Self::Value,
268+
index: Self::Value,
269+
) -> Self::Value;
270+
263271
fn call(
264272
&mut self,
265273
llfn: Self::Value,

src/librustc_codegen_ssa/traits/intrinsic.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ pub trait IntrinsicCallMethods<'tcx>: BackendTypes {
1515
args: &[OperandRef<'tcx, Self::Value>],
1616
llresult: Self::Value,
1717
span: Span,
18+
caller_instance: ty::Instance<'tcx>,
1819
);
1920

2021
fn abort(&mut self);

src/librustc_hir/lang_items.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,8 @@ language_item_table! {
242242

243243
StartFnLangItem, "start", start_fn, Target::Fn;
244244

245+
CountCodeRegionFnLangItem, "count_code_region", count_code_region_fn, Target::Fn;
246+
245247
EhPersonalityLangItem, "eh_personality", eh_personality, Target::Fn;
246248
EhCatchTypeinfoLangItem, "eh_catch_typeinfo", eh_catch_typeinfo, Target::Static;
247249

0 commit comments

Comments
 (0)