1+ use crate :: builder:: Builder ;
12use crate :: common:: CodegenCx ;
23use log:: debug;
3- use rustc_codegen_ssa:: traits:: CoverageInfoMethods ;
4- use rustc_hir:: def_id:: LOCAL_CRATE ;
4+ use rustc_codegen_ssa:: coverageinfo:: map:: * ;
5+ use rustc_codegen_ssa:: traits:: { CoverageInfoBuilderMethods , CoverageInfoMethods } ;
6+ use rustc_data_structures:: fx:: FxHashMap ;
7+ use rustc_middle:: ty:: Instance ;
58
6- // FIXME(richkadel): This might not be where I put the coverage map generation, but it's a
7- // placeholder for now.
8- //
9- // I need to inject the coverage map into the LLVM IR. This is one possible place to do it.
10- //
11- // The code below is here, at least temporarily, to verify that the `CoverageRegion`s are
12- // available, to produce the coverage map.
9+ use std:: cell:: RefCell ;
10+
11+ /// A context object for maintaining all state needed by the coverageinfo module.
12+ pub struct CrateCoverageContext < ' tcx > {
13+ // Coverage region data for each instrumented function identified by DefId.
14+ pub ( crate ) coverage_regions : RefCell < FxHashMap < Instance < ' tcx > , FunctionCoverageRegions > > ,
15+ }
16+
17+ impl < ' tcx > CrateCoverageContext < ' tcx > {
18+ pub fn new ( ) -> Self {
19+ Self { coverage_regions : Default :: default ( ) }
20+ }
21+ }
1322
1423/// Generates and exports the Coverage Map.
24+ // FIXME(richkadel): Actually generate and export the coverage map to LLVM.
25+ // The current implementation is actually just debug messages to show the data is available.
1526pub fn finalize ( cx : & CodegenCx < ' _ , ' _ > ) {
16- let instances = & * cx. instances . borrow ( ) ;
17- for instance in instances. keys ( ) {
18- if instance. def_id ( ) . krate == LOCAL_CRATE {
19- // FIXME(richkadel): Is this check `krate == LOCAL_CRATE` right?
20- //
21- // NOTE: I'm considering at least one alternative to this loop on `instances`,
22- // But if I do go with this, make sure the check on LOCAL_CRATE works for all cases.
23- //
24- //
25- // Without it, I was crashing on some of the instances, with:
26- //
27- // src/librustc_metadata/rmeta/decoder.rs:1127:17: get_optimized_mir: missing MIR for `DefId(1:2867 ~ std[70cc]::io[0]::stdio[0]::_print[0])`
28- //
29- // This check avoids it, but still works for the very limited testing I've done so far.
30- let coverageinfo = cx. tcx . coverageinfo ( instance. def_id ( ) ) ;
31- if coverageinfo. num_counters > 0 {
32- debug ! (
33- "Generate coverage map for: {}, hash: {:?}, num_counters: {}\n {}" ,
34- instance,
35- coverageinfo. hash,
36- coverageinfo. num_counters,
37- {
38- let regions = & coverageinfo. coverage_regions;
39- ( 0 ..regions. len( ) as u32 )
40- . map( |counter_index| {
41- let region = & regions[ counter_index] ;
42- format!(
43- " counter_index {} byte range: {}..{}" ,
44- counter_index, region. start_byte_pos, region. end_byte_pos
45- )
46- } )
47- . collect:: <Vec <String >>( )
48- . join( "\n " )
49- }
50- ) ;
27+ let coverage_regions = & * cx. coverage_context ( ) . coverage_regions . borrow ( ) ;
28+ for instance in coverage_regions. keys ( ) {
29+ let coverageinfo = cx. tcx . coverageinfo ( instance. def_id ( ) ) ;
30+ debug_assert ! ( coverageinfo. num_counters > 0 ) ;
31+ debug ! (
32+ "Generate coverage map for: {:?}, hash: {}, num_counters: {}" ,
33+ instance, coverageinfo. hash, coverageinfo. num_counters
34+ ) ;
35+ let function_coverage_regions = & coverage_regions[ instance] ;
36+ for ( index, region) in function_coverage_regions. indexed_regions ( ) {
37+ match region. kind {
38+ CoverageKind :: Counter => debug ! (
39+ " Counter {}, for {}..{}" ,
40+ index, region. coverage_span. start_byte_pos, region. coverage_span. end_byte_pos
41+ ) ,
42+ CoverageKind :: CounterExpression ( lhs, op, rhs) => debug ! (
43+ " CounterExpression {} = {} {:?} {}, for {}..{}" ,
44+ index,
45+ lhs,
46+ op,
47+ rhs,
48+ region. coverage_span. start_byte_pos,
49+ region. coverage_span. end_byte_pos
50+ ) ,
5151 }
5252 }
53+ for unreachable in function_coverage_regions. unreachable_regions ( ) {
54+ debug ! (
55+ " Unreachable code region: {}..{}" ,
56+ unreachable. start_byte_pos, unreachable. end_byte_pos
57+ ) ;
58+ }
5359 }
5460}
5561
@@ -58,3 +64,49 @@ impl CoverageInfoMethods for CodegenCx<'ll, 'tcx> {
5864 finalize ( self )
5965 }
6066}
67+
68+ impl CoverageInfoBuilderMethods < ' tcx > for Builder < ' a , ' ll , ' tcx > {
69+ fn new_counter_region (
70+ & mut self ,
71+ instance : Instance < ' tcx > ,
72+ index : u32 ,
73+ start_byte_pos : u32 ,
74+ end_byte_pos : u32 ,
75+ ) {
76+ let mut coverage_regions = self . coverage_context ( ) . coverage_regions . borrow_mut ( ) ;
77+ coverage_regions
78+ . entry ( instance)
79+ . or_insert_with ( || FunctionCoverageRegions :: new ( ) )
80+ . new_counter ( index, start_byte_pos, end_byte_pos) ;
81+ }
82+
83+ fn new_counter_expression_region (
84+ & mut self ,
85+ instance : Instance < ' tcx > ,
86+ index : u32 ,
87+ lhs : u32 ,
88+ op : CounterOp ,
89+ rhs : u32 ,
90+ start_byte_pos : u32 ,
91+ end_byte_pos : u32 ,
92+ ) {
93+ let mut coverage_regions = self . coverage_context ( ) . coverage_regions . borrow_mut ( ) ;
94+ coverage_regions
95+ . entry ( instance)
96+ . or_insert_with ( || FunctionCoverageRegions :: new ( ) )
97+ . new_counter_expression ( index, lhs, op, rhs, start_byte_pos, end_byte_pos) ;
98+ }
99+
100+ fn new_unreachable_region (
101+ & mut self ,
102+ instance : Instance < ' tcx > ,
103+ start_byte_pos : u32 ,
104+ end_byte_pos : u32 ,
105+ ) {
106+ let mut coverage_regions = self . coverage_context ( ) . coverage_regions . borrow_mut ( ) ;
107+ coverage_regions
108+ . entry ( instance)
109+ . or_insert_with ( || FunctionCoverageRegions :: new ( ) )
110+ . new_unreachable ( start_byte_pos, end_byte_pos) ;
111+ }
112+ }
0 commit comments