diff options
Diffstat (limited to 'compiler/rustc_codegen_ssa/src')
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/back/link.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/back/symbol_export.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/back/write.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/coverageinfo/map.rs | 25 | ||||
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/mir/coverageinfo.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/traits/coverageinfo.rs | 33 | ||||
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/traits/mod.rs | 4 |
7 files changed, 57 insertions, 15 deletions
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index b11821b7db0..4d6bc838130 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -1746,7 +1746,7 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>( ); // OBJECT-FILES-NO, AUDIT-ORDER - if sess.opts.cg.profile_generate.enabled() || sess.opts.debugging_opts.instrument_coverage { + if sess.opts.cg.profile_generate.enabled() || sess.instrument_coverage() { cmd.pgo_gen(); } diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs index 9a6f8cde1b2..abad8281d3a 100644 --- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs +++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs @@ -188,9 +188,7 @@ fn exported_symbols_provider_local( } } - if tcx.sess.opts.debugging_opts.instrument_coverage - || tcx.sess.opts.cg.profile_generate.enabled() - { + if tcx.sess.instrument_coverage() || tcx.sess.opts.cg.profile_generate.enabled() { // These are weak symbols that point to the profile version and the // profile name, which need to be treated as exported so LTO doesn't nix // them. diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 490b3d33112..7a8d8fb1304 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -176,7 +176,7 @@ impl ModuleConfig { // The rustc option `-Zinstrument_coverage` injects intrinsic calls to // `llvm.instrprof.increment()`, which requires the LLVM `instrprof` pass. - if sess.opts.debugging_opts.instrument_coverage { + if sess.instrument_coverage() { passes.push("instrprof".to_owned()); } passes diff --git a/compiler/rustc_codegen_ssa/src/coverageinfo/map.rs b/compiler/rustc_codegen_ssa/src/coverageinfo/map.rs index af6482fdbc2..7a17bced1c0 100644 --- a/compiler/rustc_codegen_ssa/src/coverageinfo/map.rs +++ b/compiler/rustc_codegen_ssa/src/coverageinfo/map.rs @@ -31,27 +31,44 @@ pub struct Expression { pub struct FunctionCoverage<'tcx> { instance: Instance<'tcx>, source_hash: u64, + is_used: bool, counters: IndexVec<CounterValueReference, Option<CodeRegion>>, expressions: IndexVec<InjectedExpressionIndex, Option<Expression>>, unreachable_regions: Vec<CodeRegion>, } impl<'tcx> FunctionCoverage<'tcx> { + /// Creates a new set of coverage data for a used (called) function. pub fn new(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> Self { + Self::create(tcx, instance, true) + } + + /// Creates a new set of coverage data for an unused (never called) function. + pub fn unused(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> Self { + Self::create(tcx, instance, false) + } + + fn create(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>, is_used: bool) -> Self { let coverageinfo = tcx.coverageinfo(instance.def_id()); debug!( - "FunctionCoverage::new(instance={:?}) has coverageinfo={:?}", - instance, coverageinfo + "FunctionCoverage::new(instance={:?}) has coverageinfo={:?}. is_used={}", + instance, coverageinfo, is_used ); Self { instance, source_hash: 0, // will be set with the first `add_counter()` + is_used, counters: IndexVec::from_elem_n(None, coverageinfo.num_counters as usize), expressions: IndexVec::from_elem_n(None, coverageinfo.num_expressions as usize), unreachable_regions: Vec::new(), } } + /// Returns true for a used (called) function, and false for an unused function. + pub fn is_used(&self) -> bool { + self.is_used + } + /// Sets the function source hash value. If called multiple times for the same function, all /// calls should have the same hash value. pub fn set_function_source_hash(&mut self, source_hash: u64) { @@ -128,8 +145,8 @@ impl<'tcx> FunctionCoverage<'tcx> { &'a self, ) -> (Vec<CounterExpression>, impl Iterator<Item = (Counter, &'a CodeRegion)>) { assert!( - self.source_hash != 0, - "No counters provided the source_hash for function: {:?}", + self.source_hash != 0 || !self.is_used, + "No counters provided the source_hash for used function: {:?}", self.instance ); diff --git a/compiler/rustc_codegen_ssa/src/mir/coverageinfo.rs b/compiler/rustc_codegen_ssa/src/mir/coverageinfo.rs index 5ab1baafb57..e2f75b2e337 100644 --- a/compiler/rustc_codegen_ssa/src/mir/coverageinfo.rs +++ b/compiler/rustc_codegen_ssa/src/mir/coverageinfo.rs @@ -33,7 +33,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let coverageinfo = bx.tcx().coverageinfo(instance.def_id()); - let fn_name = bx.create_pgo_func_name_var(instance); + let fn_name = bx.get_pgo_func_name_var(instance); let hash = bx.const_u64(function_source_hash); let num_counters = bx.const_u32(coverageinfo.num_counters); let index = bx.const_u32(u32::from(id)); diff --git a/compiler/rustc_codegen_ssa/src/traits/coverageinfo.rs b/compiler/rustc_codegen_ssa/src/traits/coverageinfo.rs index 95bddfb4b41..c7157528396 100644 --- a/compiler/rustc_codegen_ssa/src/traits/coverageinfo.rs +++ b/compiler/rustc_codegen_ssa/src/traits/coverageinfo.rs @@ -1,14 +1,41 @@ use super::BackendTypes; +use rustc_hir::def_id::DefId; use rustc_middle::mir::coverage::*; use rustc_middle::ty::Instance; -pub trait CoverageInfoMethods: BackendTypes { +pub trait CoverageInfoMethods<'tcx>: BackendTypes { fn coverageinfo_finalize(&self); -} -pub trait CoverageInfoBuilderMethods<'tcx>: BackendTypes { + /// 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 coverage `CodeRegion`s from the MIR and add + /// them. The first `CodeRegion` is used to add a single counter, with the + /// same counter ID used in the injected `instrprof.increment` intrinsic + /// call. Since the function is never called, all other `CodeRegion`s can be + /// added as `unreachable_region`s. + fn define_unused_fn(&self, def_id: DefId); + + /// For LLVM codegen, returns a function-specific `Value` for a global + /// string, to hold the function name passed to LLVM intrinsic + /// `instrprof.increment()`. The `Value` is only created once per instance. + /// Multiple invocations with the same instance return the same `Value`. + fn get_pgo_func_name_var(&self, instance: Instance<'tcx>) -> Self::Value; + + /// Creates a new PGO function name variable. This should only be called + /// to fill in the unused function names array. fn create_pgo_func_name_var(&self, instance: Instance<'tcx>) -> Self::Value; +} +pub trait CoverageInfoBuilderMethods<'tcx>: BackendTypes { /// Returns true if the function source hash was added to the coverage map (even if it had /// already been added, for this instance). Returns false *only* if `-Z instrument-coverage` is /// not enabled (a coverage map is not being generated). diff --git a/compiler/rustc_codegen_ssa/src/traits/mod.rs b/compiler/rustc_codegen_ssa/src/traits/mod.rs index 8ada6c10479..be2e0ea230f 100644 --- a/compiler/rustc_codegen_ssa/src/traits/mod.rs +++ b/compiler/rustc_codegen_ssa/src/traits/mod.rs @@ -58,7 +58,7 @@ pub trait CodegenMethods<'tcx>: + MiscMethods<'tcx> + ConstMethods<'tcx> + StaticMethods - + CoverageInfoMethods + + CoverageInfoMethods<'tcx> + DebugInfoMethods<'tcx> + AsmMethods + PreDefineMethods<'tcx> @@ -74,7 +74,7 @@ impl<'tcx, T> CodegenMethods<'tcx> for T where + MiscMethods<'tcx> + ConstMethods<'tcx> + StaticMethods - + CoverageInfoMethods + + CoverageInfoMethods<'tcx> + DebugInfoMethods<'tcx> + AsmMethods + PreDefineMethods<'tcx> |
