implemented query for coverage data

This commit adds a query that allows the CoverageData to be pulled from
a call on tcx, avoiding the need to change the
`codegen_intrinsic_call()` signature (no need to pass in the FunctionCx
or any additional arguments.

The commit does not change where/when the CoverageData is computed. It's
still done in the `pass`, and saved in the MIR `Body`.

See discussion (in progress) here:
https://github.com/rust-lang/rust/pull/73488#discussion_r443825646
This commit is contained in:
Rich Kadel 2020-06-22 14:11:55 -07:00
parent 933fe80577
commit f4a79385cf
6 changed files with 25 additions and 13 deletions

View file

@ -16,7 +16,6 @@ use rustc_codegen_ssa::common::TypeKind;
use rustc_codegen_ssa::glue;
use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue};
use rustc_codegen_ssa::mir::place::PlaceRef;
use rustc_codegen_ssa::mir::FunctionCx;
use rustc_codegen_ssa::traits::*;
use rustc_codegen_ssa::MemFlags;
use rustc_hir as hir;
@ -82,14 +81,14 @@ fn get_simple_intrinsic(cx: &CodegenCx<'ll, '_>, name: &str) -> Option<&'ll Valu
}
impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
fn codegen_intrinsic_call<'b, Bx: BuilderMethods<'b, 'tcx>>(
fn codegen_intrinsic_call(
&mut self,
fx: &FunctionCx<'b, 'tcx, Bx>,
instance: ty::Instance<'tcx>,
fn_abi: &FnAbi<'tcx, Ty<'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);
@ -141,8 +140,11 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
self.call(llfn, &[], None)
}
"count_code_region" => {
let coverage_data = fx.mir.coverage_data.as_ref().unwrap();
let mangled_fn = tcx.symbol_name(fx.instance);
let coverage_data = tcx
.coverage_data(caller_instance.def_id())
.as_ref()
.expect("LLVM intrinsic count_code_region call has associated coverage_data");
let mangled_fn = tcx.symbol_name(caller_instance);
let (mangled_fn_name, _len_val) = self.const_str(mangled_fn.name);
let hash = self.const_u64(coverage_data.hash);
let index = args[0].immediate();

View file

@ -688,12 +688,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
.collect();
bx.codegen_intrinsic_call(
self,
*instance.as_ref().unwrap(),
&fn_abi,
&args,
dest,
terminator.source_info.span,
self.instance,
);
if let ReturnDest::IndirectOperand(dst, _) = ret_dest {

View file

@ -21,9 +21,9 @@ use self::operand::{OperandRef, OperandValue};
/// Master context for codegenning from MIR.
pub struct FunctionCx<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> {
pub instance: Instance<'tcx>,
instance: Instance<'tcx>,
pub mir: &'tcx mir::Body<'tcx>,
mir: &'tcx mir::Body<'tcx>,
debug_context: Option<FunctionDebugContext<Bx::DIScope>>,

View file

@ -1,7 +1,5 @@
use super::BackendTypes;
use crate::mir::operand::OperandRef;
use crate::mir::FunctionCx;
use crate::traits::BuilderMethods;
use rustc_middle::ty::{self, Ty};
use rustc_span::Span;
use rustc_target::abi::call::FnAbi;
@ -10,14 +8,14 @@ pub trait IntrinsicCallMethods<'tcx>: BackendTypes {
/// Remember to add all intrinsics here, in librustc_typeck/check/mod.rs,
/// and in libcore/intrinsics.rs; if you need access to any llvm intrinsics,
/// add them to librustc_codegen_llvm/context.rs
fn codegen_intrinsic_call<'a, Bx: BuilderMethods<'a, 'tcx>>(
fn codegen_intrinsic_call(
&mut self,
fx: &FunctionCx<'a, 'tcx, Bx>,
instance: ty::Instance<'tcx>,
fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
args: &[OperandRef<'tcx, Self::Value>],
llresult: Self::Value,
span: Span,
caller_instance: ty::Instance<'tcx>,
);
fn abort(&mut self);

View file

@ -214,6 +214,12 @@ rustc_queries! {
cache_on_disk_if { key.is_local() }
}
query coverage_data(key: DefId) -> Option<mir::CoverageData> {
desc { |tcx| "retrieving coverage data, if computed from MIR for `{}`", tcx.def_path_str(key) }
storage(ArenaCacheSelector<'tcx>)
cache_on_disk_if { key.is_local() }
}
query promoted_mir(key: DefId) -> IndexVec<mir::Promoted, mir::Body<'tcx>> {
desc { |tcx| "optimizing promoted MIR for `{}`", tcx.def_path_str(key) }
storage(ArenaCacheSelector<'tcx>)

View file

@ -6,7 +6,7 @@ use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
use rustc_index::vec::IndexVec;
use rustc_middle::mir::visit::Visitor as _;
use rustc_middle::mir::{traversal, Body, ConstQualifs, MirPhase, Promoted};
use rustc_middle::mir::{traversal, Body, ConstQualifs, CoverageData, MirPhase, Promoted};
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::steal::Steal;
use rustc_middle::ty::{InstanceDef, TyCtxt, TypeFoldable};
@ -53,6 +53,7 @@ pub(crate) fn provide(providers: &mut Providers<'_>) {
mir_drops_elaborated_and_const_checked,
optimized_mir,
is_mir_available,
coverage_data,
promoted_mir,
..*providers
};
@ -422,6 +423,11 @@ fn run_optimization_passes<'tcx>(
);
}
fn coverage_data(tcx: TyCtxt<'_>, def_id: DefId) -> Option<CoverageData> {
let body = tcx.optimized_mir(def_id);
body.coverage_data.clone()
}
fn optimized_mir(tcx: TyCtxt<'_>, def_id: DefId) -> Body<'_> {
if tcx.is_constructor(def_id) {
// There's no reason to run all of the MIR passes on constructors when