@@ -5,7 +5,7 @@ use rustc_abi::Size;
5
5
use rustc_codegen_ssa:: traits:: {
6
6
BuilderMethods , ConstCodegenMethods , CoverageInfoBuilderMethods , MiscCodegenMethods ,
7
7
} ;
8
- use rustc_data_structures:: fx:: { FxHashMap , FxIndexSet } ;
8
+ use rustc_data_structures:: fx:: { FxHashMap , FxIndexMap } ;
9
9
use rustc_middle:: mir:: coverage:: CoverageKind ;
10
10
use rustc_middle:: ty:: Instance ;
11
11
use tracing:: { debug, instrument} ;
@@ -20,9 +20,14 @@ mod mapgen;
20
20
21
21
/// Extra per-CGU context/state needed for coverage instrumentation.
22
22
pub ( crate ) struct CguCoverageContext < ' ll , ' tcx > {
23
- /// Coverage data for each instrumented function identified by DefId.
24
- pub ( crate ) instances_used : RefCell < FxIndexSet < Instance < ' tcx > > > ,
25
- pub ( crate ) pgo_func_name_var_map : RefCell < FxHashMap < Instance < ' tcx > , & ' ll llvm:: Value > > ,
23
+ /// Associates function instances with an LLVM global that holds the
24
+ /// function's symbol name, as needed by LLVM coverage intrinsics.
25
+ ///
26
+ /// Instances in this map are also considered "used" for the purposes of
27
+ /// emitting covfun records. Every covfun record holds a hash of its
28
+ /// symbol name, and `llvm-cov` will exit fatally if it can't resolve that
29
+ /// hash back to an entry in the binary's `__llvm_prf_names` linker section.
30
+ pub ( crate ) pgo_func_name_var_map : RefCell < FxIndexMap < Instance < ' tcx > , & ' ll llvm:: Value > > ,
26
31
pub ( crate ) mcdc_condition_bitmap_map : RefCell < FxHashMap < Instance < ' tcx > , Vec < & ' ll llvm:: Value > > > ,
27
32
28
33
covfun_section_name : OnceCell < CString > ,
@@ -31,7 +36,6 @@ pub(crate) struct CguCoverageContext<'ll, 'tcx> {
31
36
impl < ' ll , ' tcx > CguCoverageContext < ' ll , ' tcx > {
32
37
pub ( crate ) fn new ( ) -> Self {
33
38
Self {
34
- instances_used : RefCell :: < FxIndexSet < _ > > :: default ( ) ,
35
39
pgo_func_name_var_map : Default :: default ( ) ,
36
40
mcdc_condition_bitmap_map : Default :: default ( ) ,
37
41
covfun_section_name : Default :: default ( ) ,
@@ -53,6 +57,14 @@ impl<'ll, 'tcx> CguCoverageContext<'ll, 'tcx> {
53
57
. and_then ( |bitmap_map| bitmap_map. get ( decision_depth as usize ) )
54
58
. copied ( ) // Dereference Option<&&Value> to Option<&Value>
55
59
}
60
+
61
+ /// Returns the list of instances considered "used" in this CGU, as
62
+ /// inferred from the keys of `pgo_func_name_var_map`.
63
+ pub ( crate ) fn instances_used ( & self ) -> Vec < Instance < ' tcx > > {
64
+ // Collecting into a Vec is way easier than trying to juggle RefCell
65
+ // projections, and this should only run once per CGU anyway.
66
+ self . pgo_func_name_var_map . borrow ( ) . keys ( ) . copied ( ) . collect :: < Vec < _ > > ( )
67
+ }
56
68
}
57
69
58
70
impl < ' ll , ' tcx > CodegenCx < ' ll , ' tcx > {
@@ -78,7 +90,10 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
78
90
/// string, to hold the function name passed to LLVM intrinsic
79
91
/// `instrprof.increment()`. The `Value` is only created once per instance.
80
92
/// Multiple invocations with the same instance return the same `Value`.
81
- fn get_pgo_func_name_var ( & self , instance : Instance < ' tcx > ) -> & ' ll llvm:: Value {
93
+ ///
94
+ /// This has the side-effect of causing coverage codegen to consider this
95
+ /// function "used", making it eligible to emit an associated covfun record.
96
+ fn ensure_pgo_func_name_var ( & self , instance : Instance < ' tcx > ) -> & ' ll llvm:: Value {
82
97
debug ! ( "getting pgo_func_name_var for instance={:?}" , instance) ;
83
98
let mut pgo_func_name_var_map = self . coverage_cx ( ) . pgo_func_name_var_map . borrow_mut ( ) ;
84
99
pgo_func_name_var_map. entry ( instance) . or_insert_with ( || {
@@ -102,7 +117,7 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> {
102
117
return ;
103
118
}
104
119
105
- let fn_name = self . get_pgo_func_name_var ( instance) ;
120
+ let fn_name = self . ensure_pgo_func_name_var ( instance) ;
106
121
let hash = self . const_u64 ( function_coverage_info. function_source_hash ) ;
107
122
let bitmap_bits = self . const_u32 ( function_coverage_info. mcdc_bitmap_bits as u32 ) ;
108
123
self . mcdc_parameters ( fn_name, hash, bitmap_bits) ;
@@ -151,19 +166,14 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> {
151
166
return ;
152
167
} ;
153
168
154
- // Mark the instance as used in this CGU, for coverage purposes.
155
- // This includes functions that were not partitioned into this CGU,
156
- // but were MIR-inlined into one of this CGU's functions.
157
- coverage_cx. instances_used . borrow_mut ( ) . insert ( instance) ;
158
-
159
169
match * kind {
160
170
CoverageKind :: SpanMarker | CoverageKind :: BlockMarker { .. } => unreachable ! (
161
171
"marker statement {kind:?} should have been removed by CleanupPostBorrowck"
162
172
) ,
163
173
CoverageKind :: VirtualCounter { bcb }
164
174
if let Some ( & id) = ids_info. phys_counter_for_node . get ( & bcb) =>
165
175
{
166
- let fn_name = bx. get_pgo_func_name_var ( instance) ;
176
+ let fn_name = bx. ensure_pgo_func_name_var ( instance) ;
167
177
let hash = bx. const_u64 ( function_coverage_info. function_source_hash ) ;
168
178
let num_counters = bx. const_u32 ( ids_info. num_counters ) ;
169
179
let index = bx. const_u32 ( id. as_u32 ( ) ) ;
@@ -193,7 +203,7 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> {
193
203
"bitmap index of the decision out of range"
194
204
) ;
195
205
196
- let fn_name = bx. get_pgo_func_name_var ( instance) ;
206
+ let fn_name = bx. ensure_pgo_func_name_var ( instance) ;
197
207
let hash = bx. const_u64 ( function_coverage_info. function_source_hash ) ;
198
208
let bitmap_index = bx. const_u32 ( bitmap_idx) ;
199
209
bx. mcdc_tvbitmap_update ( fn_name, hash, bitmap_index, cond_bitmap) ;
0 commit comments