diff options
| author | Rich Kadel <richkadel@google.com> | 2020-06-03 21:19:34 -0700 |
|---|---|---|
| committer | Rich Kadel <richkadel@google.com> | 2020-06-15 16:50:10 -0700 |
| commit | 5068ae1ca05b2be0c2a98206a58d894aa620b312 (patch) | |
| tree | 258a6eafab4eeab5d40cf776cc09d9799276787d /src/librustc_codegen_llvm | |
| parent | 395256a5dd74ccef046083d6e025a6d046379040 (diff) | |
| download | rust-5068ae1ca05b2be0c2a98206a58d894aa620b312.tar.gz rust-5068ae1ca05b2be0c2a98206a58d894aa620b312.zip | |
[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.
Diffstat (limited to 'src/librustc_codegen_llvm')
| -rw-r--r-- | src/librustc_codegen_llvm/builder.rs | 27 | ||||
| -rw-r--r-- | src/librustc_codegen_llvm/context.rs | 2 | ||||
| -rw-r--r-- | src/librustc_codegen_llvm/intrinsic.rs | 21 | ||||
| -rw-r--r-- | src/librustc_codegen_llvm/llvm/ffi.rs | 1 |
4 files changed, 51 insertions, 0 deletions
diff --git a/src/librustc_codegen_llvm/builder.rs b/src/librustc_codegen_llvm/builder.rs index f5ae9824df8..ba285b5ef38 100644 --- a/src/librustc_codegen_llvm/builder.rs +++ b/src/librustc_codegen_llvm/builder.rs @@ -997,6 +997,33 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { self.call_lifetime_intrinsic("llvm.lifetime.end.p0i8", ptr, size); } + fn instrprof_increment( + &mut self, + fn_name: &'ll Value, + hash: &'ll Value, + num_counters: &'ll Value, + index: &'ll Value, + ) -> &'ll Value { + debug!( + "instrprof_increment() with args ({:?}, {:?}, {:?}, {:?})", + fn_name, hash, num_counters, index + ); + + let llfn = unsafe { llvm::LLVMRustGetInstrprofIncrementIntrinsic(self.cx().llmod) }; + let args = &[fn_name, hash, num_counters, index]; + let args = self.check_call("call", llfn, args); + + unsafe { + llvm::LLVMRustBuildCall( + self.llbuilder, + llfn, + args.as_ptr() as *const &llvm::Value, + args.len() as c_uint, + None, + ) + } + } + fn call( &mut self, llfn: &'ll Value, diff --git a/src/librustc_codegen_llvm/context.rs b/src/librustc_codegen_llvm/context.rs index 4c810a37d41..7ff5ac5cbdc 100644 --- a/src/librustc_codegen_llvm/context.rs +++ b/src/librustc_codegen_llvm/context.rs @@ -749,6 +749,8 @@ impl CodegenCx<'b, 'tcx> { ifn!("llvm.lifetime.start.p0i8", fn(t_i64, i8p) -> void); ifn!("llvm.lifetime.end.p0i8", fn(t_i64, i8p) -> void); + ifn!("llvm.instrprof.increment", fn(i8p, t_i64, t_i32, t_i32) -> void); + ifn!("llvm.expect.i1", fn(i1, i1) -> i1); ifn!("llvm.eh.typeid.for", fn(i8p) -> t_i32); ifn!("llvm.localescape", fn(...) -> void); diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs index 1e6d2e3dbb7..7fddda99185 100644 --- a/src/librustc_codegen_llvm/intrinsic.rs +++ b/src/librustc_codegen_llvm/intrinsic.rs @@ -7,6 +7,8 @@ use crate::type_of::LayoutLlvmExt; use crate::va_arg::emit_va_arg; use crate::value::Value; +use log::debug; + use rustc_ast::ast; use rustc_codegen_ssa::base::{compare_simd_types, to_immediate, wants_msvc_seh}; use rustc_codegen_ssa::common::span_invalid_monomorphization_error; @@ -21,6 +23,7 @@ use rustc_middle::ty::layout::{FnAbiExt, HasTyCtxt}; use rustc_middle::ty::{self, Ty}; use rustc_middle::{bug, span_bug}; use rustc_span::Span; +use rustc_span::Symbol; use rustc_target::abi::{self, HasDataLayout, LayoutOf, Primitive}; use rustc_target::spec::PanicStrategy; @@ -86,6 +89,7 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { args: &[OperandRef<'tcx, &'ll Value>], llresult: &'ll Value, span: Span, + caller_instance: ty::Instance<'tcx>, ) { let tcx = self.tcx; let callee_ty = instance.monomorphic_ty(tcx); @@ -136,6 +140,23 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { let llfn = self.get_intrinsic(&("llvm.debugtrap")); self.call(llfn, &[], None) } + "count_code_region" => { + if let ty::InstanceDef::Item(fn_def_id) = caller_instance.def { + let caller_fn_path = tcx.def_path_str(fn_def_id); + debug!( + "count_code_region to llvm.instrprof.increment(fn_name={})", + caller_fn_path + ); + + let (fn_name, _len_val) = self.const_str(Symbol::intern(&caller_fn_path)); + let index = args[0].immediate(); + let hash = self.const_u64(1234); + let num_counters = self.const_u32(1); + self.instrprof_increment(fn_name, hash, num_counters, index) + } else { + bug!("intrinsic count_code_region: no src.instance"); + } + } "va_start" => self.va_start(args[0].immediate()), "va_end" => self.va_end(args[0].immediate()), "va_copy" => { diff --git a/src/librustc_codegen_llvm/llvm/ffi.rs b/src/librustc_codegen_llvm/llvm/ffi.rs index 54cf99e1c6d..372fb17573a 100644 --- a/src/librustc_codegen_llvm/llvm/ffi.rs +++ b/src/librustc_codegen_llvm/llvm/ffi.rs @@ -1360,6 +1360,7 @@ extern "C" { // Miscellaneous instructions pub fn LLVMBuildPhi(B: &Builder<'a>, Ty: &'a Type, Name: *const c_char) -> &'a Value; + pub fn LLVMRustGetInstrprofIncrementIntrinsic(M: &Module) -> &'a Value; pub fn LLVMRustBuildCall( B: &Builder<'a>, Fn: &'a Value, |
