From 56a3e068057e4accb8d6c6182f70b59a7ee622b0 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Thu, 7 Sep 2023 22:49:28 +1000 Subject: [PATCH] !! (WIP) Per-function coverage table --- .../src/coverageinfo/map_data.rs | 9 +++++-- .../src/coverageinfo/mapgen.rs | 5 +++- .../src/coverageinfo/mod.rs | 3 --- compiler/rustc_middle/src/mir/coverage.rs | 13 +++------- .../rustc_mir_transform/src/coverage/mod.rs | 25 +++++++++---------- .../rustc_mir_transform/src/coverage/query.rs | 17 +++++++------ ...ument_coverage.bar.InstrumentCoverage.diff | 1 - ...ment_coverage.main.InstrumentCoverage.diff | 4 --- 8 files changed, 36 insertions(+), 41 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs index 7da441cbe8e01..07bf4c02da373 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs @@ -3,6 +3,7 @@ use crate::coverageinfo::ffi::{Counter, CounterExpression, ExprKind}; use rustc_data_structures::fx::{FxHashMap, FxIndexSet}; use rustc_index::bit_set::BitSet; use rustc_index::IndexVec; +use rustc_middle::mir; use rustc_middle::mir::coverage::{CodeRegion, CounterId, CovTerm, ExpressionId, Op}; use rustc_middle::ty::Instance; use rustc_middle::ty::TyCtxt; @@ -129,7 +130,7 @@ impl<'tcx> FunctionCoverage<'tcx> { self.add_mappings(CovTerm::Zero, std::slice::from_ref(code_region)); } - pub(crate) fn add_mappings(&mut self, kind: CovTerm, code_regions: &[CodeRegion]) { + fn add_mappings(&mut self, kind: CovTerm, code_regions: &[CodeRegion]) { // There's no need to sort the regions by filename before grouping here, // because the result is the same either way. for regions_for_file in code_regions.group_by(|a, b| a.file_name == b.file_name) { @@ -140,7 +141,11 @@ impl<'tcx> FunctionCoverage<'tcx> { } } - pub(crate) fn finalize(&mut self) { + pub(crate) fn finalize(&mut self, coverage_info: &mir::coverage::FunctionCoverageInfo) { + for &(mapping_kind, ref code_region) in &coverage_info.mappings { + self.add_mappings(mapping_kind, std::slice::from_ref(code_region)); + } + let zero_expressions = self.simplify_expressions_and_get_zero_expressions(); let mapping_kind_sort_key = |mapping_kind: &CovTerm| match mapping_kind { diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs index 22ed1cc98cb6d..edc42520cc6b0 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs @@ -61,7 +61,10 @@ pub fn finalize(cx: &CodegenCx<'_, '_>) { let mut function_data = Vec::new(); for (instance, mut function_coverage) in function_coverage_map { debug!("Generate function coverage for {}, {:?}", cx.codegen_unit.name(), instance); - function_coverage.finalize(); + let Some(coverage_info) = tcx.instance_mir(instance.def).coverage_info.as_ref() else { + continue; + }; + function_coverage.finalize(coverage_info); let function_coverage = function_coverage; let mangled_function_name = tcx.symbol_name(instance).name; diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs index 6af96b6a0fc61..74955b83bc2a5 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs @@ -137,9 +137,6 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> { CoverageKind::Expression { id, lhs, op, rhs } => { func_coverage.add_expression_data(id, lhs, op, rhs); } - CoverageKind::Mappings { kind, ref code_regions } => { - func_coverage.add_mappings(kind, code_regions); - } } } } diff --git a/compiler/rustc_middle/src/mir/coverage.rs b/compiler/rustc_middle/src/mir/coverage.rs index 91b0a49e5716f..aabaa6860ea19 100644 --- a/compiler/rustc_middle/src/mir/coverage.rs +++ b/compiler/rustc_middle/src/mir/coverage.rs @@ -75,10 +75,6 @@ pub enum CoverageKind { op: Op, rhs: CovTerm, }, - Mappings { - kind: CovTerm, - code_regions: Vec, - }, } impl Debug for CoverageKind { @@ -97,11 +93,6 @@ impl Debug for CoverageKind { }, rhs, ), - Mappings { kind, code_regions } => fmt - .debug_struct("Mappings") - .field("kind", kind) - .field("code_regions", code_regions) - .finish(), } } } @@ -144,4 +135,6 @@ impl Op { } #[derive(Clone, Debug, TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)] -pub struct FunctionCoverageInfo {} +pub struct FunctionCoverageInfo { + pub mappings: Vec<(CovTerm, CodeRegion)>, +} diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs index 47bcfbf6646b6..a50af36d31651 100644 --- a/compiler/rustc_mir_transform/src/coverage/mod.rs +++ b/compiler/rustc_mir_transform/src/coverage/mod.rs @@ -107,6 +107,7 @@ struct Instrumentor<'a, 'tcx> { function_source_hash: u64, basic_coverage_blocks: CoverageGraph, coverage_counters: CoverageCounters, + mappings: Vec<(CovTerm, CodeRegion)>, } impl<'a, 'tcx> Instrumentor<'a, 'tcx> { @@ -148,6 +149,7 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> { function_source_hash, basic_coverage_blocks, coverage_counters, + mappings: Vec::new(), } } @@ -276,6 +278,9 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> { self.make_mir_coverage_kind(intermediate_expression), ); } + + self.mir_body.coverage_info = + Some(Box::new(FunctionCoverageInfo { mappings: std::mem::take(&mut self.mappings) })); } /// Injects a single [`StatementKind::Coverage`] for each BCB that has one @@ -305,20 +310,14 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> { debug_used_expressions.add_expression_operands(&counter_kind); graphviz_data.add_bcb_coverage_spans_with_counter(bcb, bcb_spans, &counter_kind); - // Convert the coverage spans into a vector of code regions to be - // associated with this BCB's coverage statement. - let code_regions = bcb_spans - .iter() - .map(|coverage_span| { - make_code_region(source_map, file_name, coverage_span.span, body_span) - }) - .collect::>(); + let mapping_kind = counter_kind.as_term(); + self.mappings.extend(bcb_spans.iter().map(|coverage_span| { + ( + mapping_kind, + make_code_region(source_map, file_name, coverage_span.span, body_span), + ) + })); - inject_statement( - self.mir_body, - CoverageKind::Mappings { kind: counter_kind.as_term(), code_regions }, - mir::START_BLOCK, - ); inject_statement( self.mir_body, self.make_mir_coverage_kind(&counter_kind), diff --git a/compiler/rustc_mir_transform/src/coverage/query.rs b/compiler/rustc_mir_transform/src/coverage/query.rs index 6440f2b8fffbc..2436c7d7404fe 100644 --- a/compiler/rustc_mir_transform/src/coverage/query.rs +++ b/compiler/rustc_mir_transform/src/coverage/query.rs @@ -58,6 +58,12 @@ impl CoverageVisitor { for coverage in all_coverage_in_mir_body(body) { self.visit_coverage(coverage); } + + for (mapping_kind, _code_region) in + body.coverage_info.iter().flat_map(|coverage_info| &coverage_info.mappings) + { + self.update_from_term(*mapping_kind); + } } fn visit_coverage(&mut self, coverage: &Coverage) { @@ -68,7 +74,6 @@ impl CoverageVisitor { self.update_from_term(lhs); self.update_from_term(rhs); } - CoverageKind::Mappings { kind, .. } => self.update_from_term(kind), } } } @@ -92,12 +97,10 @@ fn coverageinfo<'tcx>(tcx: TyCtxt<'tcx>, instance_def: ty::InstanceDef<'tcx>) -> fn covered_code_regions(tcx: TyCtxt<'_>, def_id: DefId) -> Vec<&CodeRegion> { let body = mir_body(tcx, def_id); - all_coverage_in_mir_body(body) - // Only `Mappings` statements have a list of code regions. - .flat_map(|coverage| match coverage.kind { - CoverageKind::Mappings { ref code_regions, .. } => code_regions.as_slice(), - _ => &[], - }) + body.coverage_info + .iter() + .flat_map(|coverage_info| &coverage_info.mappings) + .map(|(_mapping_kind, code_region)| code_region) .collect() } diff --git a/tests/mir-opt/instrument_coverage.bar.InstrumentCoverage.diff b/tests/mir-opt/instrument_coverage.bar.InstrumentCoverage.diff index a89d345ac6dbb..6a59d8b0b2049 100644 --- a/tests/mir-opt/instrument_coverage.bar.InstrumentCoverage.diff +++ b/tests/mir-opt/instrument_coverage.bar.InstrumentCoverage.diff @@ -6,7 +6,6 @@ bb0: { + Coverage::Counter(0); -+ Coverage::Mappings { kind: Counter(0), code_regions: [/the/src/instrument_coverage.rs:20:1 - 22:2] }; _0 = const true; return; } diff --git a/tests/mir-opt/instrument_coverage.main.InstrumentCoverage.diff b/tests/mir-opt/instrument_coverage.main.InstrumentCoverage.diff index c1872218a4fbc..57c221cb26381 100644 --- a/tests/mir-opt/instrument_coverage.main.InstrumentCoverage.diff +++ b/tests/mir-opt/instrument_coverage.main.InstrumentCoverage.diff @@ -8,11 +8,7 @@ let mut _3: !; bb0: { -+ Coverage::Mappings { kind: Counter(1), code_regions: [/the/src/instrument_coverage.rs:15:10 - 15:11] }; -+ Coverage::Mappings { kind: Expression(1), code_regions: [/the/src/instrument_coverage.rs:14:13 - 14:18, /the/src/instrument_coverage.rs:17:1 - 17:2] }; -+ Coverage::Mappings { kind: Expression(0), code_regions: [/the/src/instrument_coverage.rs:12:5 - 13:17] }; + Coverage::Counter(0); -+ Coverage::Mappings { kind: Counter(0), code_regions: [/the/src/instrument_coverage.rs:11:1 - 11:11] }; goto -> bb1; }