forked from rust-lang/rust
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Rollup merge of rust-lang#73684 - richkadel:llvm-coverage-map-gen-2, …
…r=wesleywiser add spans to injected coverage counters, extract with CoverageData query This is the next iteration on the Rust Coverage implementation, and follows PR rust-lang#73488 @tmandry @wesleywiser I came up with an approach for coverage spans, pushing them through the Call terminator as additional args so they can be extracted by the CoverageData query. I'm using an IndexVec to store them in CoverageData such that there can be only one per index (even if parts of the MIR get duplicated during optimization). If this approach works for you, I can quickly expand on this to build a separate IndexVec for counter expressions, using a separate call that will be ignored during code generation, but from which I can extract the counter expression values. Let me know your thoughts. Thanks! r? @tmandry Rust compiler MCP rust-lang/compiler-team#278 Relevant issue: rust-lang#34701 - Implement support for LLVMs code coverage instrumentation
- Loading branch information
Showing
27 changed files
with
585 additions
and
93 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
use crate::builder::Builder; | ||
use crate::common::CodegenCx; | ||
use log::debug; | ||
use rustc_codegen_ssa::coverageinfo::map::*; | ||
use rustc_codegen_ssa::traits::{CoverageInfoBuilderMethods, CoverageInfoMethods}; | ||
use rustc_data_structures::fx::FxHashMap; | ||
use rustc_middle::ty::Instance; | ||
|
||
use std::cell::RefCell; | ||
|
||
/// A context object for maintaining all state needed by the coverageinfo module. | ||
pub struct CrateCoverageContext<'tcx> { | ||
// Coverage region data for each instrumented function identified by DefId. | ||
pub(crate) coverage_regions: RefCell<FxHashMap<Instance<'tcx>, FunctionCoverageRegions>>, | ||
} | ||
|
||
impl<'tcx> CrateCoverageContext<'tcx> { | ||
pub fn new() -> Self { | ||
Self { coverage_regions: Default::default() } | ||
} | ||
} | ||
|
||
/// Generates and exports the Coverage Map. | ||
// FIXME(richkadel): Actually generate and export the coverage map to LLVM. | ||
// The current implementation is actually just debug messages to show the data is available. | ||
pub fn finalize(cx: &CodegenCx<'_, '_>) { | ||
let coverage_regions = &*cx.coverage_context().coverage_regions.borrow(); | ||
for instance in coverage_regions.keys() { | ||
let coverageinfo = cx.tcx.coverageinfo(instance.def_id()); | ||
debug_assert!(coverageinfo.num_counters > 0); | ||
debug!( | ||
"Generate coverage map for: {:?}, hash: {}, num_counters: {}", | ||
instance, coverageinfo.hash, coverageinfo.num_counters | ||
); | ||
let function_coverage_regions = &coverage_regions[instance]; | ||
for (index, region) in function_coverage_regions.indexed_regions() { | ||
match region.kind { | ||
CoverageKind::Counter => debug!( | ||
" Counter {}, for {}..{}", | ||
index, region.coverage_span.start_byte_pos, region.coverage_span.end_byte_pos | ||
), | ||
CoverageKind::CounterExpression(lhs, op, rhs) => debug!( | ||
" CounterExpression {} = {} {:?} {}, for {}..{}", | ||
index, | ||
lhs, | ||
op, | ||
rhs, | ||
region.coverage_span.start_byte_pos, | ||
region.coverage_span.end_byte_pos | ||
), | ||
} | ||
} | ||
for unreachable in function_coverage_regions.unreachable_regions() { | ||
debug!( | ||
" Unreachable code region: {}..{}", | ||
unreachable.start_byte_pos, unreachable.end_byte_pos | ||
); | ||
} | ||
} | ||
} | ||
|
||
impl CoverageInfoMethods for CodegenCx<'ll, 'tcx> { | ||
fn coverageinfo_finalize(&self) { | ||
finalize(self) | ||
} | ||
} | ||
|
||
impl CoverageInfoBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> { | ||
fn add_counter_region( | ||
&mut self, | ||
instance: Instance<'tcx>, | ||
index: u32, | ||
start_byte_pos: u32, | ||
end_byte_pos: u32, | ||
) { | ||
debug!( | ||
"adding counter to coverage map: instance={:?}, index={}, byte range {}..{}", | ||
instance, index, start_byte_pos, end_byte_pos, | ||
); | ||
let mut coverage_regions = self.coverage_context().coverage_regions.borrow_mut(); | ||
coverage_regions.entry(instance).or_default().add_counter( | ||
index, | ||
start_byte_pos, | ||
end_byte_pos, | ||
); | ||
} | ||
|
||
fn add_counter_expression_region( | ||
&mut self, | ||
instance: Instance<'tcx>, | ||
index: u32, | ||
lhs: u32, | ||
op: CounterOp, | ||
rhs: u32, | ||
start_byte_pos: u32, | ||
end_byte_pos: u32, | ||
) { | ||
debug!( | ||
"adding counter expression to coverage map: instance={:?}, index={}, {} {:?} {}, byte range {}..{}", | ||
instance, index, lhs, op, rhs, start_byte_pos, end_byte_pos, | ||
); | ||
let mut coverage_regions = self.coverage_context().coverage_regions.borrow_mut(); | ||
coverage_regions.entry(instance).or_default().add_counter_expression( | ||
index, | ||
lhs, | ||
op, | ||
rhs, | ||
start_byte_pos, | ||
end_byte_pos, | ||
); | ||
} | ||
|
||
fn add_unreachable_region( | ||
&mut self, | ||
instance: Instance<'tcx>, | ||
start_byte_pos: u32, | ||
end_byte_pos: u32, | ||
) { | ||
debug!( | ||
"adding unreachable code to coverage map: instance={:?}, byte range {}..{}", | ||
instance, start_byte_pos, end_byte_pos, | ||
); | ||
let mut coverage_regions = self.coverage_context().coverage_regions.borrow_mut(); | ||
coverage_regions.entry(instance).or_default().add_unreachable(start_byte_pos, end_byte_pos); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.