coverage: Emit mappings for unused functions without generating stubs
This commit is contained in:
parent
249624b504
commit
e964ea5bf5
2 changed files with 37 additions and 74 deletions
|
@ -1,6 +1,5 @@
|
|||
use crate::llvm;
|
||||
|
||||
use crate::abi::Abi;
|
||||
use crate::builder::Builder;
|
||||
use crate::common::CodegenCx;
|
||||
use crate::coverageinfo::ffi::{CounterExpression, CounterMappingRegion};
|
||||
|
@ -12,17 +11,13 @@ use rustc_codegen_ssa::traits::{
|
|||
StaticMethods,
|
||||
};
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_llvm::RustString;
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::mir::coverage::{CounterId, CoverageKind, FunctionCoverageInfo};
|
||||
use rustc_middle::mir::coverage::{CoverageKind, FunctionCoverageInfo};
|
||||
use rustc_middle::mir::Coverage;
|
||||
use rustc_middle::ty;
|
||||
use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt};
|
||||
use rustc_middle::ty::GenericArgs;
|
||||
use rustc_middle::ty::Instance;
|
||||
use rustc_middle::ty::Ty;
|
||||
use rustc_middle::ty::layout::HasTyCtxt;
|
||||
use rustc_middle::ty::{self, GenericArgs, Instance, TyCtxt};
|
||||
|
||||
use std::cell::RefCell;
|
||||
|
||||
|
@ -30,8 +25,6 @@ pub(crate) mod ffi;
|
|||
pub(crate) mod map_data;
|
||||
pub mod mapgen;
|
||||
|
||||
const UNUSED_FUNCTION_COUNTER_ID: CounterId = CounterId::START;
|
||||
|
||||
const VAR_ALIGN_BYTES: usize = 8;
|
||||
|
||||
/// A context object for maintaining all state needed by the coverageinfo module.
|
||||
|
@ -77,22 +70,8 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Functions with MIR-based coverage are normally codegenned _only_ if
|
||||
/// called. LLVM coverage tools typically expect every function to be
|
||||
/// defined (even if unused), with at least one call to LLVM intrinsic
|
||||
/// `instrprof.increment`.
|
||||
///
|
||||
/// Codegen a small function that will never be called, with one counter
|
||||
/// that will never be incremented.
|
||||
///
|
||||
/// For used/called functions, the coverageinfo was already added to the
|
||||
/// `function_coverage_map` (keyed by function `Instance`) during codegen.
|
||||
/// But in this case, since the unused function was _not_ previously
|
||||
/// codegenned, collect the function coverage info from MIR and add an
|
||||
/// "unused" entry to the function coverage map.
|
||||
fn define_unused_fn(&self, def_id: DefId, function_coverage_info: &'tcx FunctionCoverageInfo) {
|
||||
let instance = declare_unused_fn(self, def_id);
|
||||
codegen_unused_fn_and_counter(self, instance);
|
||||
let instance = declare_unused_fn(self.tcx, def_id);
|
||||
add_unused_function_coverage(self, instance, function_coverage_info);
|
||||
}
|
||||
}
|
||||
|
@ -159,10 +138,8 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn declare_unused_fn<'tcx>(cx: &CodegenCx<'_, 'tcx>, def_id: DefId) -> Instance<'tcx> {
|
||||
let tcx = cx.tcx;
|
||||
|
||||
let instance = Instance::new(
|
||||
fn declare_unused_fn<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Instance<'tcx> {
|
||||
Instance::new(
|
||||
def_id,
|
||||
GenericArgs::for_item(tcx, def_id, |param, _| {
|
||||
if let ty::GenericParamDefKind::Lifetime = param.kind {
|
||||
|
@ -171,46 +148,7 @@ fn declare_unused_fn<'tcx>(cx: &CodegenCx<'_, 'tcx>, def_id: DefId) -> Instance<
|
|||
tcx.mk_param_from_def(param)
|
||||
}
|
||||
}),
|
||||
);
|
||||
|
||||
let llfn = cx.declare_fn(
|
||||
tcx.symbol_name(instance).name,
|
||||
cx.fn_abi_of_fn_ptr(
|
||||
ty::Binder::dummy(tcx.mk_fn_sig(
|
||||
[Ty::new_unit(tcx)],
|
||||
Ty::new_unit(tcx),
|
||||
false,
|
||||
hir::Unsafety::Unsafe,
|
||||
Abi::Rust,
|
||||
)),
|
||||
ty::List::empty(),
|
||||
),
|
||||
None,
|
||||
);
|
||||
|
||||
llvm::set_linkage(llfn, llvm::Linkage::PrivateLinkage);
|
||||
llvm::set_visibility(llfn, llvm::Visibility::Default);
|
||||
|
||||
assert!(cx.instances.borrow_mut().insert(instance, llfn).is_none());
|
||||
|
||||
instance
|
||||
}
|
||||
|
||||
fn codegen_unused_fn_and_counter<'tcx>(cx: &CodegenCx<'_, 'tcx>, instance: Instance<'tcx>) {
|
||||
let llfn = cx.get_fn(instance);
|
||||
let llbb = Builder::append_block(cx, llfn, "unused_function");
|
||||
let mut bx = Builder::build(cx, llbb);
|
||||
let fn_name = bx.get_pgo_func_name_var(instance);
|
||||
let hash = bx.const_u64(0);
|
||||
let num_counters = bx.const_u32(1);
|
||||
let index = bx.const_u32(u32::from(UNUSED_FUNCTION_COUNTER_ID));
|
||||
debug!(
|
||||
"codegen intrinsic instrprof.increment(fn_name={:?}, hash={:?}, num_counters={:?},
|
||||
index={:?}) for unused function: {:?}",
|
||||
fn_name, hash, num_counters, index, instance
|
||||
);
|
||||
bx.instrprof_increment(fn_name, hash, num_counters, index);
|
||||
bx.ret_void();
|
||||
)
|
||||
}
|
||||
|
||||
fn add_unused_function_coverage<'tcx>(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue